Pointers II — Arithmetic, Arrays, Function Params
pointer + array + function — C-র শক্তির ত্রয়ী
1. Pointer Arithmetic
একটি pointer-এ 1 যোগ করা মানে সেই pointer-এর type-এর পরবর্তী element-এ যাওয়া — এক byte নয়, এক element।
#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
#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।
#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-তেও দেখা যায়।
#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
int *bad() { int x = 42; return &x; } — function শেষ হলে x ধ্বংস হয়, পরে সেই address-এ access করা undefined behavior। Return করতে পারেন static/global, heap-এ allocate করা মেমরি বা caller-এর দেওয়া buffer।
7. The sizeof Surprise
#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
- 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; } - 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; } - 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; } - 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; } - Implement
strcpyusing 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; } - 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; } - 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; } - Demonstrate
sizeof(array)vssizeof(pointer)side by side.sizeof(array)ওsizeof(pointer)পাশাপাশি দেখান।✨ Show Answer
Section 7-এর
sizeof_fn.c-ই সম্পূর্ণ উত্তর। - 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; } - Implement
memcpyusingvoid *.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; } - Implement
memsetusingvoid *.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; } - Why is
void *useful? Give two examples.void *-এর উপকারিতা — দুটি উদাহরণ।✨ Show Answer
void *"any pointer" হিসেবে কাজ করে — আপনি যেকোনো pointer তাতে রাখতে পারেন, আবার বের করে cast করতে পারেন। ব্যবহার:
(১)malloc/memcpy/memsetযেকোনো type-এর মেমরি নিয়ে কাজ করে, তাই তাদের parametervoid *।
(২)qsort-এর compare function generic — সেটিওconst void *parameter নেয়। এভাবে C-তে generic programming সম্ভব হয়। - Explain why
p++on anint *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 করে। - 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; } - 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; } - 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; } - 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 করতে পারে, এমনকি আজ এক ক্রম, কাল আরেক ক্রম। তাই আচরণ অনির্দিষ্ট।==ও!=তুলনা অবশ্য বৈধ। - 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; } - 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; } - Fix this bug:
int a[10]; int *p = a; while(*p) printf("%d", *p++);উপরের কোডের বাগ খুঁজে ঠিক করুন।✨ Show Answer
সমস্যা:
auninitialized, তাই প্রথম 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; } - Read the declaration
int *(*fp)(int)and explain what it is.int *(*fp)(int)পড়ে ব্যাখ্যা করুন।✨ Show Answer
fpহলো একটি pointer যা একটি function-এর দিকে নির্দেশ করে — সেই function একটিintparameter নেয় এবং একটিint *(int-এর pointer) return করে। - 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 (শব্দকোষ)
| Term | Meaning | বাংলায় |
|---|---|---|
| Pointer Arithmetic | Adding/subtracting integers from a pointer; advances by element size. | Pointer-এ যোগ/বিয়োগ — element size অনুযায়ী এগোয়। |
| Array Decay | Array 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-array | A pointer with the array's full type — does not decay. | Array-র সম্পূর্ণ type-যুক্ত pointer। |
sizeof on a pointer | Inside a function, returns pointer size — not the array's. | Function-এর ভিতরে শুধু pointer-এর size। |
| Pass-by-Pointer | Passing 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 Pointer | T * const — pointer itself cannot be reassigned. | Pointer নিজে পরিবর্তন করা যাবে না। |
| Pointer to Const | const T * — cannot modify the pointed-at data. | Pointed data পরিবর্তন করা যাবে না। |
| Pointer Difference | Subtracting two pointers in the same array — gives element count. | একই array-র দুই pointer-এর পার্থক্য — element সংখ্যা। |
| Returning Local Address | Bug — 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.