某軟件公司筆試題:「請寫一個宏,計算靜態數組的元素個數」。標準答案:
#define countof(arr) sizeof(arr)/sizeof(arr[0])
若改用函數:
int countof(void *arr) {
return sizeof(arr)/sizeof(arr[0]); // 錯誤!
}
答案:無法實現預期功能。
sizeof 是操作符而非函數,其值在編譯階段確定。對於靜態數組,編譯器知道完整類型資訊,能計算整個數組大小;但傳遞給函數時,數組退化為指針,類型資訊丟失。
函數參數 void *arr 接收的是數組首元素地址(指針)。在 32 位系統上,sizeof(void*) == 4,與元素類型無關。
#include <iostream>
int getNum(void *pArr) {
return sizeof(pArr); // 僅返回指針大小
}
int _tmain(int argc, _TCHAR* argv[]) {
int myArr[10];
int *pTest = new int(10); // 動態分配單個 int,非數組
int myParam[10];
char myChar[10];
std::cout << "sizeof(int): " << sizeof(int) << std::endl; // 4
std::cout << "myArr: " << sizeof(myArr) << std::endl; // 40 (10*4)
std::cout << "pTest: " << sizeof(pTest) << std::endl; // 4 (指針)
std::cout << "getNum(myParam): " << getNum(myParam) << std::endl; // 4
std::cout << "getNum(myChar): " << getNum(myChar) << std::endl; // 4
return 0;
}
sizeof(int): 4
myArr: 40
pTest: 4
getNum(myParam): 4
getNum(myChar): 4
sizeof 關鍵字 返回與變量或類型關聯的存儲字節數……
當應用於靜態維度數組時,sizeof 返回整個數組的大小。
sizeof 操作符不能返回動態分配的數組或外部數組的大小。
#define countof(arr) (sizeof(arr)/sizeof((arr)[0])) —— 在調用點保留完整類型資訊,編譯期計算,零開銷。template <typename T, size_t N> constexpr size_t countof(T(&)[N]) { return N; } —— 類型安全、編譯期計算、拒絕指針退化。std::vector/std::span)。這道題考察的不僅是 sizeof 語法,更是對 C/C++ 類型系統、編譯期與運行期邊界、參數傳遞機制 的深度理解。