const, volatile, restrict

const

變數宣告成 const 代表「我們不會透過這個變數寫入該段記憶體」,但我們還是可以透過其他方式修改 const 指向的記憶體,只是不能透過宣告為 const 的變數

int value = 10;
const int *ptr = &value;
 
// *ptr = 20;  // error: can't write by ptr
value = 20;
 
printf("%d\n", *ptr);  // 20

volatile

我們宣告變數為 volatile 是在告訴編譯器,這個變數的值可能因為編譯器現在看不見的東西(signal handler、其他 process)而改變,所以不要做太激進的優化

static int foo;
 
void bar(void) {
    foo = 0;
    while (foo != 255)
        ...
}

當編譯器讀到上面的程式碼,他會發現 foo != 255 永遠會成立,所以就可能將其優化成

void bar_optimized(void) {
    foo = 0;
    while (true)  // wait forever!
        ...
}

但是實際上 foo == 255 可能會因為 signal handler 或其他原因成立

restrict

restrict 只能用於宣告 pointer,它的意思是「我保證這個指標是存取它所指向物件的唯一方式」,也就是說沒有其他指標會指向同一塊記憶體,這可以讓編譯器使用更激進的優化

void *memcpy(void *restrict s1, const void *restrict s2, size_t n);
void *memmove(void *s1, const void *s2, size_t n);

memcpy 使用 restrict,這告訴編譯器「來源和目標記憶體區域不會重疊」。這讓編譯器可以做更激進的優化,比如一次複製多個 bytes,或使用 SIMD 指令

memmove 沒有使用 restrict,所以它必須處理來源和目標重疊的情況,需要更小心地複製,確保即使記憶體重疊也能正確工作