#include
#include
void main(int i) {
printf("%d ", i);
(&main + (&exit - &main) * (i/1000))(i+1);
}
void main(int i) 非標準簽名,但某些環境(如 Linux x86)啟動時會將 argc 傳入 i,初始值為 1。i/1000:i < 1000 時為 0,表達式簡化為 (&main + 0)(i+1) → 呼叫 main(i+1),形成遞迴。i == 1000,i/1000 = 1,表達式變為 (&main + (&exit - &main)) = &exit,呼叫 exit(1001)。exit 參數為 int,但實際返回給作業系統的是 status & 0xFF(低 8 位)。1001 % 256 = 233,故 echo $? 輸出 233。1 2 3 ... 999 1000
main 標準簽名僅 int main()、int main(int argc, char* argv[])、int main(int argc, char** argv)。&exit - &main 依賴函式在記憶體中相對位置,屬未定義行為(UB)。a[5] == 5[a]
int a[] = {1,2,3,4,5,6};
printf("a[5]=%-5d 5[a]=%-5d", a[5], 5[a]); // 皆輸出 6
C 標準定義 E1[E2] ≡ *((E1)+(E2))。
因此:
a[5] → *(a + 5)5[a] → *(5 + a)指標加法符合交換律,兩者完全等價。這是 C 語言設計初期為了方便編譯器實作而定下的規則,也是 MIT 經典面試題。
a[5] 為何不寫成 *(5+a)?因為習慣把陣列名放左邊,語義更清晰。a 是指標而非陣列,規則同樣適用。a[i] 其實是 *(a+i),陣列名在表達式中自動退化為首元素指標。