Advanced Pointers — const, restrict, volatile

Pointer qualifier — যা বেশিরভাগ শেখে না

~35 min Advanced 12 practice problems Live code

1. const — Placement Matters

const_demo.c
#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;
}
Spiral rule Declaration পড়ার সময় variable name থেকে বাইরের দিকে ঘুরিয়ে পড়ুন।

2. restrict (C99)

Compiler-কে প্রতিশ্রুতি: এই pointer-ই underlying memory access-এর একমাত্র path। ফলে aggressive optimization (loop vectorization ইত্যাদি) সম্ভব।

restrict.c
#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 ব্যবহার করুন।

punning.c
#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

  1. 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 plain int * — সব পরিষ্কার।

  2. Function with two restrict params — show it helps compiler.
    Restrict দিয়ে vec_add।
    ✨ Show Answer

    Section 2 reference। -O2-এ godbolt.org-এ assembly দেখুন — SIMD instructions appear।

  3. 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.
  4. 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);
  5. 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;
  6. 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-এ।

  7. Why does volatile not guarantee thread safety?
    Volatile কেন thread-safe নয়?
    ✨ Show Answer

    Volatile শুধু reordering prevent করে না, atomicity দেয় না, memory barrier দেয় না। Multithreading-এ C11 _Atomic বা <stdatomic.h> ব্যবহার করুন।

  8. 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 হয়।

  9. 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-ই রাখে।

  10. 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 করবে।

  11. 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 *।

  12. 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 (শব্দকোষ)

TermMeaningবাংলায়
Type QualifierA keyword (const, volatile, restrict) modifying a type.Type পরিবর্তনকারী keyword।
constThe data must not be modified through this pointer/lvalue.এই path-এ data পরিবর্তন করা যাবে না।
Pointer-to-constconst T *p — cannot modify *p.*p পরিবর্তন করা যাবে না।
Const PointerT * const p — cannot reassign p.p নিজে পরিবর্তন করা যাবে না।
volatileTells the compiler the value may change unexpectedly — no caching.মান হঠাৎ বদলাতে পারে — caching নয়।
restrictPromise that no other pointer aliases this one — enables optimization.অন্য pointer alias নয় — optimization সক্রিয় করে।
AliasingTwo pointers referring to the same memory.দুটি pointer একই memory-তে নির্দেশ।
Strict Aliasing RuleYou may not access an object through a pointer of incompatible type.অসামঞ্জস্যপূর্ণ type-এর pointer দিয়ে access করা যাবে না।
Memory-Mapped I/OHardware registers exposed at fixed memory addresses (use volatile).হার্ডওয়্যার register-এর memory address (volatile দরকার)।
Compiler OptimizationCode transformations that preserve semantics but improve speed/size.একই semantics-এ দ্রুততর/ছোট কোড।
Cast Away constRemoving const via a cast — usually undefined behavior.const জোর করে সরানো — সাধারণত UB।
memcpy TrickType-punning safely without violating aliasing.Aliasing না ভেঙে type-pun-এর নিরাপদ উপায়।

Summary — Module 36

const intent প্রকাশ করে; restrict optimization enable করে; volatile caching আটকায়। typedef ব্যবহার করুন। Strict aliasing মানুন বা memcpy ব্যবহার করুন।

Next Module → Processes & IPC।