首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 語言 sizeof 操作符深度解析:函數名作為運算元的行為與標準規定

     編輯:程式設計綜合問答

現象

int func() { return 0; }
printf("%zu\n", sizeof(func)); // 輸出 1 (GCC/Clang) 或編譯錯誤 (MSVC)

為什麼 sizeof(func) 結果是 1?為什麼不報錯?

標準規定 (C99/C11/C17)

C 標準 6.5.3.4/1:

sizeof 運算元可以是類型名稱或運算式。若為運算式,**不求值**,只根據運算式的類型推導大小。

函數名在運算式中的類型

  • 函數名 func 在大多數上下文會隱式轉換為 **函數指標** int (*)()
  • 但 sizeof、_Alignof、& (取址) 是**例外**,函數名保持 **函數類型** int ()

為什麼是 1?GCC 的歷史兼容性擴展

GCC 文檔明確說明:

對於 sizeof(函數類型),GCC 定義其大小為 1,以便於指標運算兼容性(早期代碼可能做 ptr + sizeof(func) 類似操作)。這是 GNU 擴展,**非標準行為**。

各編譯器行為對比

標準視角的「為什麼」

C 標準規定:不完整類型不可作為 sizeof 運算元。函數類型 int () 屬於不完整類型(無長度、無佈局),因此標準合規編譯器**必須報錯**。GCC 為了兼容舊代碼,選擇給出 1 並警告,而非硬性報錯。

正確做法

  • 想要函數指標大小:sizeof(&func) 或 sizeof(int(*)())
  • 想要函數機器碼大小:**C 標準無法獲取**,需平台特定手段(如 objdump、鏈接器映射文件)
  • 編寫可移植代碼:永遠不要對函數名直接使用 sizeof

相關陷阱:數組參數退化

void foo(int arr[100]) {
    printf("%zu\n", sizeof(arr)); // 輸出指標大小 (4/8),非 400!
    // 參數實際為 int *arr,數組信息丟失
}

總結

sizeof(func) == 1 是 **GCC 的非標準擴展**,為歷史兼容性而存在。標準 C 規定函數類型不完整,不可用 sizeof,合規編譯器會報錯。編寫可移植代碼時,**避免對函數名使用 sizeof**,改用 sizeof(&func) 獲取指標大小,或查閱平台文檔獲取機器碼大小。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
編譯器sizeof(func)sizeof(&func)標準合規性
GCC / Clang1 (警告: "sizeof on function type returns 1")指標大小 (4/8)GNU 擴展,非標準
MSVC編譯錯誤 C2070: "illegal sizeof operand"指標大小嚴格遵循標準
標準 C**約束違規**,必須診斷指標大小函數類型不完整,不可用 sizeof