每個C程序員可以決定在與該公知的宏數組中元素的數目:可靠地確定數組中的元素的數量
#define NUM_ELEMS(a) (sizeof(a)/sizeof 0[a])
下面是一個典型的使用情況:
int numbers[] = {2, 3, 5, 7, 11, 13, 17, 19};
printf("%lu\n", NUM_ELEMS(numbers)); // 8, as expected
然而,沒有什麼能夠阻止意外傳遞而不是數組的指針程序員:
int * pointer = numbers;
printf("%lu\n", NUM_ELEMS(pointer));
在我的系統上,這會打印2,因爲顯然,指針的大小是整數的兩倍。我想過如何防止程序員被誤傳遞指針,我找到了一個解決方案:
#define NUM_ELEMS(a) (assert((void*)&(a) == (void*)(a)), (sizeof(a)/sizeof 0[a]))
這工作,因爲一個指向數組的指針具有相同的值作爲一個指向它的第一個元素。如果你傳遞一個指針,指針將與一個指向它自己的指針進行比較,這個指針幾乎總是假的。 (唯一的例外是一個遞歸void指針,即,一個空指針指向本身我可以忍受的。)
不留神傳遞一個陣列的指針,而不是現在觸發在運行時的誤差:
Assertion `(void*)&(pointer) == (void*)(pointer)' failed.
不錯!現在我有幾個問題:
是我的
assert
使用作爲逗號表達式有效的標準C的左操作數?也就是說,該標準是否允許我使用assert
作爲表達式?對不起,如果這是一個愚蠢的問題:)可以檢查某種方式在編譯時?
我的C編譯器認爲
int b[NUM_ELEMS(a)];
是一個VLA。任何方式說服他,否則?我是第一個想到這個嗎?如果是這樣,我可以指望有多少處女在天堂等着我呢? :)
至於第(4)部分,很確定它不是* 72.我認爲t帽子是其他東西的保留值... –
你是不是指'sizeof a [0]'? –
每一位真正的c程序員都知道,跟蹤數組的大小是他們的問題,而不是編譯器,並且「搞清楚」的技巧嚴格限制了效用,因爲這些信息只保留在範圍內。如果您希望編譯器爲您處理此問題,請使用更智能的語言。我的意思是,你只需要去C++並使用'std :: vector'或(用C++ 11)'std :: array',所以這不是一個巨大的改變。 – dmckee