首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

兩個經典奇葩 C 程式深度解析:遞迴 main 與陣列下標交換律

     編輯:關於C

程式一:遞迴呼叫 main 並最終跳轉 exit


#include 
#include 

void main(int i) {
    printf("%d ", i);
    (&main + (&exit - &main) * (i/1000))(i+1);
}

執行流程分析

  1. void main(int i) 非標準簽名,但某些環境(如 Linux x86)啟動時會將 argc 傳入 i,初始值為 1。
  2. i/1000:i < 1000 時為 0,表達式簡化為 (&main + 0)(i+1) → 呼叫 main(i+1),形成遞迴。
  3. 當 i == 1000,i/1000 = 1,表達式變為 (&main + (&exit - &main)) = &exit,呼叫 exit(1001)。
  4. 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),陣列名在表達式中自動退化為首元素指標。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved