Pointers II — Arithmetic, Arrays, Function Params

pointer + array + function — C-র শক্তির ত্রয়ী

~45 min Advanced 22 practice problems Live code

1. Pointer Arithmetic

একটি pointer-এ 1 যোগ করা মানে সেই pointer-এর type-এর পরবর্তী element-এ যাওয়া — এক byte নয়, এক element।

ptr_arith.c
#include <stdio.h>

int main(void) {
    int a[5] = {10, 20, 30, 40, 50};
    int *p = a;

    printf("*p       = %d\n", *p);
    printf("*(p+1)   = %d\n", *(p + 1));
    printf("*(p+4)   = %d\n", *(p + 4));

    printf("p        = %p\n", (void*)p);
    printf("p+1      = %p  (moves by sizeof(int) bytes)\n", (void*)(p + 1));
    return 0;
}
int *p-এ p + 1 আসলে p + sizeof(int) byte এগোয়। char *-এ এটি ১ byte, double *-এ ৮ byte — এক হাত, দুই চোখ কিন্তু ভিন্ন step।

2. Array-Pointer Equivalence

a[i]     is exactly  *(a + i)
&a[i]    is exactly   (a + i)

Array-র নাম expression-এ ব্যবহার হলে (সামান্য কিছু exception ছাড়া) তা স্বয়ংক্রিয়ভাবে তার প্রথম element-এর pointer-এ decay করে। a[i] লেখা আর *(a+i) লেখা একই কাজ।

3. Iterating with Pointers

ptr_iter.c
#include <stdio.h>

int main(void) {
    int a[5] = {11, 22, 33, 44, 55};
    int *end = a + 5;
    for (int *p = a; p < end; p++)
        printf("%d ", *p);
    putchar('\n');
    return 0;
}

4. Pointer to Pointer

Pointer-এর address-ও একটি address — সেটাকেও একটি pointer-এ সংরক্ষণ করা যায়। সাধারণ ব্যবহার: array of strings (char **argv), dynamic 2D array, linked list head modify।

pptr.c
#include <stdio.h>

int main(void) {
    int   x  = 5;
    int  *p  = &x;
    int **pp = &p;
    printf("x=%d  *p=%d  **pp=%d\n", x, *p, **pp);

    const char *names[] = { "Arif", "Nusrat", "Zahid" };
    const char **it = names;
    printf("first = %s\n", *it);
    printf("third = %s\n", *(it + 2));
    return 0;
}

5. Arrays as Function Parameters

Function-এ array পাঠালে আসলে শুধু প্রথম element-এর pointer যায় — পুরো array কপি হয় না। তাই function-এর ভেতরে পরিবর্তন করলে সেটা caller-এর original array-তেও দেখা যায়।

scale.c
#include <stdio.h>

void scale(int a[], int n, int k) {       // same as int *a
    for (int i = 0; i < n; i++) a[i] *= k;
}

int main(void) {
    int v[4] = {1, 2, 3, 4};
    scale(v, 4, 10);
    for (int i = 0; i < 4; i++) printf("%d ", v[i]);
    putchar('\n');
    return 0;
}

6. Returning Pointers — Carefully

Never return a pointer to a local variable int *bad() { int x = 42; return &x; } — function শেষ হলে x ধ্বংস হয়, পরে সেই address-এ access করা undefined behavior। Return করতে পারেন static/global, heap-এ allocate করা মেমরি বা caller-এর দেওয়া buffer।

7. The sizeof Surprise

sizeof_fn.c
#include <stdio.h>

void f(int a[]) {
    printf("inside : sizeof(a) = %zu\n", sizeof(a));
}

int main(void) {
    int a[10];
    printf("outside: sizeof(a) = %zu\n", sizeof(a));
    f(a);
    return 0;
}

Main-এ sizeof(a) 40 byte (10 × 4 ধরে), কিন্তু f-এর ভেতরে a একটি pointer — তাই sizeof 8 byte (64-bit সিস্টেমে)। সবসময় length আলাদাভাবে পাঠাতে হবে।

8. Practice Problems

  1. Print an array in reverse using pointer arithmetic only (no indexing).
    শুধু pointer arithmetic দিয়ে array reverse-এ প্রিন্ট করুন, কোনো index ব্যবহার ছাড়াই।
    ✨ Show Answer
    rev_ptr.c
    #include <stdio.h>
    int main(void) {
        int a[] = {10, 20, 30, 40, 50};
        int *end = a + 5;
        for (int *p = end - 1; p >= a; p--) printf("%d ", *p);
        putchar('\n');
        return 0;
    }
  2. Copy one array to another using pointers.
    Pointer দিয়ে একটি array থেকে আরেকটিতে কপি করুন।
    ✨ Show Answer
    copy.c
    #include <stdio.h>
    int main(void) {
        int src[] = {1, 2, 3, 4, 5};
        int dst[5];
        int *s = src, *d = dst, *end = src + 5;
        while (s < end) *d++ = *s++;
        for (int i = 0; i < 5; i++) printf("%d ", dst[i]);
        putchar('\n');
        return 0;
    }
  3. Write int *search(int *arr, int n, int x) that returns a pointer to x or NULL.
    Target পেলে pointer, না পেলে NULL return করে এমন search ফাংশন লিখুন।
    ✨ Show Answer
    search.c
    #include <stdio.h>
    #include <stddef.h>
    int *search(int *a, int n, int x) {
        for (int *p = a; p < a + n; p++)
            if (*p == x) return p;
        return NULL;
    }
    int main(void) {
        int a[] = {3, 7, 12, 19};
        int *r = search(a, 4, 12);
        if (r) printf("found %d at offset %ld\n", *r, r - a);
        else   puts("not found");
        return 0;
    }
  4. Implement size_t my_strlen(const char *s) using pointer arithmetic.
    Pointer arithmetic দিয়ে my_strlen লিখুন।
    ✨ Show Answer
    my_strlen.c
    #include <stdio.h>
    #include <stddef.h>
    size_t my_strlen(const char *s) {
        const char *p = s;
        while (*p) p++;
        return p - s;
    }
    int main(void) { printf("%zu\n", my_strlen("ABCL TECH")); return 0; }
  5. Implement strcpy using only pointers.
    Pointer দিয়ে strcpy লিখুন।
    ✨ Show Answer
    my_strcpy.c
    #include <stdio.h>
    char *my_strcpy(char *d, const char *s) {
        char *start = d;
        while ((*d++ = *s++));   // copies the '\0' too and then stops
        return start;
    }
    int main(void) {
        char buf[64];
        my_strcpy(buf, "Hello, Bangladesh!");
        puts(buf);
        return 0;
    }
  6. Reverse an array in place using two pointers (start and end).
    Start ও end দুই pointer দিয়ে array in-place reverse করুন।
    ✨ Show Answer
    rev_two_ptr.c
    #include <stdio.h>
    void rev(int *a, int n) {
        int *l = a, *r = a + n - 1;
        while (l < r) { int t = *l; *l = *r; *r = t; l++; r--; }
    }
    int main(void) {
        int a[] = {1, 2, 3, 4, 5};
        rev(a, 5);
        for (int i = 0; i < 5; i++) printf("%d ", a[i]);
        putchar('\n');
        return 0;
    }
  7. Given char **argv-like array, print all "command-line" arguments.
    char **argv-এর মতো array-র সব argument প্রিন্ট করুন।
    ✨ Show Answer
    argv_like.c
    #include <stdio.h>
    int main(void) {
        const char *argv[] = { "./prog", "--verbose", "input.txt", NULL };
        for (const char **p = argv; *p; p++)
            printf("arg: %s\n", *p);
        return 0;
    }
  8. Demonstrate sizeof(array) vs sizeof(pointer) side by side.
    sizeof(array) ও sizeof(pointer) পাশাপাশি দেখান।
    ✨ Show Answer

    Section 7-এর sizeof_fn.c-ই সম্পূর্ণ উত্তর।

  9. Write a function that takes a pointer and an index and returns a pointer to that position.
    Pointer ও index নিয়ে সেই position-এর pointer return করুন।
    ✨ Show Answer
    at.c
    #include <stdio.h>
    int *at(int *a, int i) { return a + i; }
    int main(void) {
        int a[] = {10, 20, 30, 40};
        printf("*at(a, 2) = %d\n", *at(a, 2));
        return 0;
    }
  10. Implement memcpy using void *.
    void * দিয়ে memcpy লিখুন।
    ✨ Show Answer
    my_memcpy.c
    #include <stdio.h>
    #include <stddef.h>
    
    void *my_memcpy(void *dst, const void *src, size_t n) {
        unsigned char *d = dst;
        const unsigned char *s = src;
        while (n--) *d++ = *s++;
        return dst;
    }
    
    int main(void) {
        int src[] = {11, 22, 33, 44};
        int dst[4];
        my_memcpy(dst, src, sizeof(src));
        for (int i = 0; i < 4; i++) printf("%d ", dst[i]);
        putchar('\n');
        return 0;
    }
  11. Implement memset using void *.
    void * দিয়ে memset লিখুন।
    ✨ Show Answer
    my_memset.c
    #include <stdio.h>
    #include <stddef.h>
    void *my_memset(void *p, int v, size_t n) {
        unsigned char *q = p;
        while (n--) *q++ = (unsigned char)v;
        return p;
    }
    int main(void) {
        char buf[16];
        my_memset(buf, 'X', 15); buf[15] = '\0';
        puts(buf);
        return 0;
    }
  12. Why is void * useful? Give two examples.
    void *-এর উপকারিতা — দুটি উদাহরণ।
    ✨ Show Answer

    void * "any pointer" হিসেবে কাজ করে — আপনি যেকোনো pointer তাতে রাখতে পারেন, আবার বের করে cast করতে পারেন। ব্যবহার:
    (১) malloc/memcpy/memset যেকোনো type-এর মেমরি নিয়ে কাজ করে, তাই তাদের parameter void *।
    (২) qsort-এর compare function generic — সেটিও const void * parameter নেয়। এভাবে C-তে generic programming সম্ভব হয়।

  13. Explain why p++ on an int * advances 4 bytes, not 1.
    int *-এ p++ কেন 4 byte এগোয়, 1 byte না?
    ✨ Show Answer

    Pointer arithmetic সবসময় target type-এর sizeof-এ মাপা হয়। int-এর size সাধারণত 4 byte, তাই p + 1 মানে "পরবর্তী int", অর্থাৎ 4 byte পরের address। এভাবেই a[i] == *(a + i) যথাযথ element return করে।

  14. Write in-place array rotation using pointer math only.
    Pointer math-এ in-place array rotate করুন।
    ✨ Show Answer
    rotate_ptr.c
    #include <stdio.h>
    static void rev(int *l, int *r) {
        while (l < r) { int t = *l; *l++ = *r; *r-- = t; }
    }
    void rotate_left(int *a, int n, int k) {
        k %= n;
        rev(a, a + k - 1);
        rev(a + k, a + n - 1);
        rev(a, a + n - 1);
    }
    int main(void) {
        int a[] = {1, 2, 3, 4, 5, 6, 7};
        rotate_left(a, 7, 3);
        for (int i = 0; i < 7; i++) printf("%d ", a[i]);
        putchar('\n');
        return 0;
    }
  15. Build a 2D matrix using int ** and dynamic rows.
    int ** দিয়ে dynamic 2D matrix তৈরি করুন।
    ✨ Show Answer
    matrix_2d.c
    #include <stdio.h>
    #include <stdlib.h>
    int main(void) {
        int r = 3, c = 4;
        int **m = malloc(r * sizeof(int *));
        for (int i = 0; i < r; i++) m[i] = malloc(c * sizeof(int));
    
        for (int i = 0; i < r; i++)
            for (int j = 0; j < c; j++) m[i][j] = i * c + j;
    
        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) printf("%3d ", m[i][j]);
            putchar('\n');
        }
    
        for (int i = 0; i < r; i++) free(m[i]);
        free(m);
        return 0;
    }
  16. Find the pointer difference between two elements of the same array — what type is it?
    একই array-এর দুটি pointer বিয়োগ করলে ফলাফলের type কী?
    ✨ Show Answer

    Type: ptrdiff_t (থাকে <stddef.h>-এ)। Value = দুটি pointer-এর মধ্যে কতগুলো element আছে। উদাহরণ:

    pdiff.c
    #include <stdio.h>
    #include <stddef.h>
    int main(void) {
        int a[10];
        ptrdiff_t d = (a + 7) - (a + 2);
        printf("difference = %td\n", d);   // 5
        return 0;
    }
  17. Why is comparing pointers from different arrays undefined behavior?
    ভিন্ন array-র দুটি pointer তুলনা করা কেন UB?
    ✨ Show Answer

    C standard অনুযায়ী relational operator (< > <= >=) শুধু একই array-এর (বা একটি element just past-the-end-এর) দুটি pointer-এর মধ্যে সংজ্ঞায়িত। ভিন্ন allocation-এর মধ্যে আপেক্ষিক ঠিকানা নির্ধারিত না — OS যেকোনোভাবে memory place করতে পারে, এমনকি আজ এক ক্রম, কাল আরেক ক্রম। তাই আচরণ অনির্দিষ্ট। == ও != তুলনা অবশ্য বৈধ।

  18. Using pointers, count vowels in a string.
    Pointer ব্যবহার করে একটি string-এ vowel গুনুন।
    ✨ Show Answer
    vowels.c
    #include <stdio.h>
    #include <ctype.h>
    int count_vowels(const char *s) {
        int c = 0;
        for (; *s; s++) {
            char lc = tolower((unsigned char)*s);
            if (lc=='a'||lc=='e'||lc=='i'||lc=='o'||lc=='u') c++;
        }
        return c;
    }
    int main(void) {
        printf("%d\n", count_vowels("Hello, Bangladesh!"));
        return 0;
    }
  19. Reverse a string in place using two pointers.
    দুটি pointer দিয়ে string in-place reverse করুন।
    ✨ Show Answer
    rev_str_ptr.c
    #include <stdio.h>
    #include <string.h>
    void rev(char *s) {
        char *l = s, *r = s + strlen(s) - 1;
        while (l < r) { char t = *l; *l++ = *r; *r-- = t; }
    }
    int main(void) {
        char s[] = "Bangladesh";
        rev(s);
        puts(s);
        return 0;
    }
  20. Fix this bug: int a[10]; int *p = a; while(*p) printf("%d", *p++);
    উপরের কোডের বাগ খুঁজে ঠিক করুন।
    ✨ Show Answer

    সমস্যা: a uninitialized, তাই প্রথম element-এর মান অনিশ্চিত; while (*p) সমাপ্তি নিশ্চিত করতে পারে না (কোনো sentinel নেই) — UB। সংশোধন: বাগ ছাড়া নিরাপদ sentinel-ভিত্তিক loop:

    fixed_loop.c
    #include <stdio.h>
    int main(void) {
        int a[] = {3, 7, 12, 0};       // 0 acts as sentinel
        int *p = a;
        while (*p) printf("%d ", *p++);
        putchar('\n');
        return 0;
    }
  21. Read the declaration int *(*fp)(int) and explain what it is.
    int *(*fp)(int) পড়ে ব্যাখ্যা করুন।
    ✨ Show Answer

    fp হলো একটি pointer যা একটি function-এর দিকে নির্দেশ করে — সেই function একটি int parameter নেয় এবং একটি int * (int-এর pointer) return করে।

  22. In one paragraph, explain the array-pointer equivalence rule.
    একটি অনুচ্ছেদে array-pointer equivalence ব্যাখ্যা করুন।
    ✨ Show Answer

    Expression-এ array-র নাম ব্যবহার করলে সেটি স্বয়ংক্রিয়ভাবে তার প্রথম element-এর pointer-এ decay হয়ে যায় (sizeof ও &array-এর মতো কয়েকটি ব্যতিক্রম ছাড়া)। ফলে a[i] লিখা আর *(a + i) লিখা অভিন্ন। C-র subscript operator-এর সংজ্ঞা আসলে এটিই, তাই i[a]-ও বৈধ (যদিও সচরাচর ব্যবহার হয় না)। Function argument হিসেবে array পাঠালে কেবল pointer যায়, পুরো array কপি হয় না — তাই efficient, কিন্তু length আলাদাভাবে পাঠানো জরুরি।

Glossary (শব্দকোষ)

TermMeaningবাংলায়
Pointer ArithmeticAdding/subtracting integers from a pointer; advances by element size.Pointer-এ যোগ/বিয়োগ — element size অনুযায়ী এগোয়।
Array DecayArray name automatically converts to pointer-to-first-element.Array name স্বয়ংক্রিয়ভাবে first element-এর pointer-এ পরিণত।
a[i] == *(a+i)Subscripting is defined as pointer arithmetic + dereference.Subscript আসলে pointer arithmetic + dereference।
Pointer-to-arrayA pointer with the array's full type — does not decay.Array-র সম্পূর্ণ type-যুক্ত pointer।
sizeof on a pointerInside a function, returns pointer size — not the array's.Function-এর ভিতরে শুধু pointer-এর size।
Pass-by-PointerPassing an address so the function can modify caller's data.Caller-এর data পরিবর্তনযোগ্য করতে address পাঠানো।
Pointer to Pointer (**)A pointer whose value is itself a pointer's address.Pointer-এর address ধারণকারী pointer।
Generic Pointer (void *)Untyped pointer — used by malloc, memcpy.Type-হীন pointer।
Const PointerT * const — pointer itself cannot be reassigned.Pointer নিজে পরিবর্তন করা যাবে না।
Pointer to Constconst T * — cannot modify the pointed-at data.Pointed data পরিবর্তন করা যাবে না।
Pointer DifferenceSubtracting two pointers in the same array — gives element count.একই array-র দুই pointer-এর পার্থক্য — element সংখ্যা।
Returning Local AddressBug — local variable's memory becomes invalid after return.Return-এর পর local-এর মেমরি অবৈধ হয়ে যায়।

Summary — Module 15

Pointer arithmetic steps by element size. Arrays decay to pointers. a[i] == *(a+i). Never return pointers to locals. Inside a function, sizeof(array) is pointer size.

Next Module → Strings — char array ও string.h।