Advanced Pointers — const, restrict, volatile
Pointer qualifier — যা বেশিরভাগ শেখে না
1. const — Placement Matters
#include <stdio.h>
int main(void) {
int x = 5, y = 10;
const int *p = &x; // pointer to const int — *p read-only
p = &y; // ok, p itself is mutable
// *p = 20; // error
int *const q = &x; // const pointer — *q writable, q fixed
*q = 99; // ok
// q = &y; // error
const int *const r = &x; // both const
printf("x=%d y=%d *p=%d *q=%d *r=%d\n", x, y, *p, *q, *r);
return 0;
}
2. restrict (C99)
Compiler-কে প্রতিশ্রুতি: এই pointer-ই underlying memory access-এর একমাত্র path। ফলে aggressive optimization (loop vectorization ইত্যাদি) সম্ভব।
#include <stdio.h>
void vec_add(int *restrict out,
const int *restrict a,
const int *restrict b,
int n) {
for (int i = 0; i < n; i++) out[i] = a[i] + b[i];
}
int main(void) {
int a[] = {1, 2, 3, 4};
int b[] = {10, 20, 30, 40};
int c[4];
vec_add(c, a, b, 4);
for (int i = 0; i < 4; i++) printf("%d ", c[i]);
putchar('\n');
return 0;
}
memcpy restrict নেয়, memmove নেয় না — তাই overlapping region-এ memmove।
3. volatile
volatile uint32_t *UART_STATUS = (uint32_t*)0x40011000;
while (!(*UART_STATUS & READY_BIT)) { } // hardware may change it
Hardware register, signal handler, memory-mapped I/O — এসব ক্ষেত্রে volatile compiler-কে caching করতে বাধা দেয়। Threading-এর জন্য atomic বেশি উপযোগী।
4. Reading Complex Declarations
int *(*(*fp)(int))[10];
// fp is:
// a pointer to
// a function taking int
// returning a pointer to
// an array of 10
// pointers to int
Tool: cdecl.org। Habit: সবসময় typedef দিয়ে ভেঙে লিখুন — এটাই production code-এ সঠিক practice।
5. Strict Aliasing Rule
একটি type-এর memory অন্য type-এর pointer দিয়ে access করা UB — ব্যতিক্রম: char* যেকোনো কিছু alias করতে পারে। Type punning-এ memcpy বা union ব্যবহার করুন।
#include <stdio.h>
#include <string.h>
int main(void) {
float f = 3.14f;
unsigned int bits;
// Safe type punning via memcpy — no UB
memcpy(&bits, &f, sizeof f);
printf("float %.2f → bits 0x%08X\n", f, bits);
// Also safe: via union (C99+)
union { float f; unsigned int u; } u;
u.f = f;
printf("via union: 0x%08X\n", u.u);
return 0;
}
6. Practice Problems
- Write four pointer declarations using const in different positions; explain each.চার ধরনের const pointer।
✨ Show Answer
Section 1 reference।
const int *,int *const,const int *const, and plainint *— সব পরিষ্কার। - Function with two restrict params — show it helps compiler.Restrict দিয়ে vec_add।
✨ Show Answer
Section 2 reference।
-O2-এ godbolt.org-এ assembly দেখুন — SIMD instructions appear। - Minimal memory-mapped I/O read (without real hardware).MMIO read demo।
✨ Show Answer
volatile uint32_t reg; // simulated printf("%u\n", reg); // Compiler MUST read reg each time — won't cache. - Reproduce a strict-aliasing bug; fix with memcpy.Strict-aliasing বাগ reproduce এবং ফিক্স।
✨ Show Answer
// ❌ UB — strict aliasing violation float f = 3.14f; int bits = *(int*)&f; // ✅ Safe int bits; memcpy(&bits, &f, sizeof f); - Use typedef to clean up nested function-pointer declaration.Typedef দিয়ে পরিষ্কার করা।
✨ Show Answer
// Verbose: int (*(*fp)(int))(int, int); typedef int (*BinOp)(int, int); typedef BinOp (*OpFactory)(int); OpFactory fp; - Write memcpy and memmove — explain when each is correct.memcpy vs memmove।
✨ Show Answer
memcpy: src/dst overlap না থাকলে ব্যবহারযোগ্য (restrict parameter)। memmove: overlap-এও safe — backward copy logic ব্যবহার করে dst > src-এ।
- Why does volatile not guarantee thread safety?Volatile কেন thread-safe নয়?
✨ Show Answer
Volatile শুধু reordering prevent করে না, atomicity দেয় না, memory barrier দেয় না। Multithreading-এ C11
_Atomicবা<stdatomic.h>ব্যবহার করুন। - Use restrict in vec_add; observe assembly changes at -O2.-O2-এ restrict-এর effect।
✨ Show Answer
godbolt.org-এ restrict-সহ ও ছাড়া দুই version compile করে দেখুন — restrict-এ SIMD (movdqu ইত্যাদি) instructions appear হয়।
- Why can't the compiler vectorize a loop when two pointers may alias?Alias হলে vectorization কেন সম্ভব নয়?
✨ Show Answer
Compiler জানে না loop iteration-গুলো independent কি না।
a[i+1] = b[i]-এ যদি b-ও a-র next index-এ point করে, তাহলে parallel করলে wrong result। তাই sequential-ই রাখে। - Parse:
char (*(*x[3])())[5];Complex declaration parse।✨ Show Answer
x is an array of 3 pointers to functions, each returning a pointer to an array of 5 chars। cdecl.org confirm করবে।
- Implement a const-correct my_strcat.Const-correct strcat।
✨ Show Answer
char *my_strcat(char *dst, const char *src) { char *r = dst; while (*dst) dst++; while ((*dst++ = *src++)); return r; }src shouldn't change →
const char *। dst writable →char *। - Demonstrate const-cast abuse and why it's usually a bug.Const-cast abuse।
✨ Show Answer
char *p = (char*)"literal"; p[0] = 'X';— string literal read-only segment-এ থাকে; cast দিয়ে const উঁচানো UB ও crash।
Glossary (শব্দকোষ)
| Term | Meaning | বাংলায় |
|---|---|---|
| Type Qualifier | A keyword (const, volatile, restrict) modifying a type. | Type পরিবর্তনকারী keyword। |
const | The data must not be modified through this pointer/lvalue. | এই path-এ data পরিবর্তন করা যাবে না। |
| Pointer-to-const | const T *p — cannot modify *p. | *p পরিবর্তন করা যাবে না। |
| Const Pointer | T * const p — cannot reassign p. | p নিজে পরিবর্তন করা যাবে না। |
volatile | Tells the compiler the value may change unexpectedly — no caching. | মান হঠাৎ বদলাতে পারে — caching নয়। |
restrict | Promise that no other pointer aliases this one — enables optimization. | অন্য pointer alias নয় — optimization সক্রিয় করে। |
| Aliasing | Two pointers referring to the same memory. | দুটি pointer একই memory-তে নির্দেশ। |
| Strict Aliasing Rule | You may not access an object through a pointer of incompatible type. | অসামঞ্জস্যপূর্ণ type-এর pointer দিয়ে access করা যাবে না। |
| Memory-Mapped I/O | Hardware registers exposed at fixed memory addresses (use volatile). | হার্ডওয়্যার register-এর memory address (volatile দরকার)। |
| Compiler Optimization | Code transformations that preserve semantics but improve speed/size. | একই semantics-এ দ্রুততর/ছোট কোড। |
| Cast Away const | Removing const via a cast — usually undefined behavior. | const জোর করে সরানো — সাধারণত UB। |
memcpy Trick | Type-punning safely without violating aliasing. | Aliasing না ভেঙে type-pun-এর নিরাপদ উপায়। |
Summary — Module 36
const intent প্রকাশ করে; restrict optimization enable করে; volatile caching আটকায়। typedef ব্যবহার করুন। Strict aliasing মানুন বা memcpy ব্যবহার করুন।