作者cutecpu (可愛中央處理器)
看板C_and_CPP
標題Re: [問題] 請問array size奇怪定義
時間Wed Nov 2 16:23:21 2011
※ 引述《liptonbin (wind)》之銘言:
: 請問一下
: #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) +
: __must_be_array(arr))
: 其中他的定義如下
: #define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
: #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
: #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
: 不曉得有沒有人看得懂BUILD_BUG_ON_ZERO和__same_type各式作什麼的
: 為什array_size需要多加 __must_be_array(arr)
: 謝謝
原本的確 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 就可以了
但怕你 arr 代入的是 pointer(*) 而不是 array([]),所以用一些技巧來避免誤用的情況
看底下例子:
#include <stdio.h>
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
int main(){
int array[20];
int *ptr = array;
/* 這裡代入的是 int * ,而不是 int [20] */
printf("%lu\n",ARRAY_SIZE(ptr));
return 0;
}
印出來的結果應該不是你想要的 20 XD
========= 以下來看上面那些 macro 在做啥事 =========
1. #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
其中 __builtin_types_compatible_p (type1, type2) 是 built-in function provided
by GCC,用途是比較 type1 跟 type2 是不是 compatible,如果 compatible 則回傳 1
否則為 0
2. #define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
展開之後變成,BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(typeof(a),
typeof(&(a)[0]))),剛剛前面有提到 __builtin_types_compatible_p 只會回傳 0 或 1
註:
a 如果是 array([]) 則 __builtin_types_compatible_p(typeof(a), typeof(&(a)[0]))
會回傳 0;a 如果是 pointer(*) 則回傳 1
所以 __must_be_array(a) 替換後不是 BUILD_BUG_ON_ZERO(0)
就是 BUILD_BUG_ON_ZERO(1)
3. #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
把 BUILD_BUG_ON_ZERO(0) 替換會得到:
sizeof(struct { int:0; }) <== 合法,會得到 0
把 BUILD_BUG_ON_ZERO(1) 替換會得到:
sizeof(struct { int:-1; }) <== 不合法,bit-field 的 width 不能為負,
所以 compile 會報錯,也利用這一點來達到靠 compile 來避免誤用的情況
========= 結論 =========
以上是我 google 英、簡、中說明加上做些小實驗後的理解,哈哈XD
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 210.59.164.109
→ angleevil:樓上是神 11/02 16:55
推 LPH66:話說這讓我想到 VC2005 的 _countof... (ref.#18GQ0GzF) 11/02 17:01
→ LPH66:那個用的方法需要一點 template 的概念才看得懂 XD" 11/02 17:02
→ hilorrk:static assertion? 11/02 19:30
推 hilorrk:cool! 11/02 21:38
推 VictorTom:推, 太強大了Orz 11/02 23:09
推 tropical72:cutecpu 好強!! 補一下, struct {int:0;} 大小應不是 11/02 23:31
→ tropical72:確定的,depends on compiler ? 11/02 23:31
推 hilorrk:「大小不確定」的說法不太正確,因為0-width bit-field是 11/03 00:29
→ hilorrk:align,由於它一定是unnamed(沒有declarator) 所以也沒有 11/03 00:31
→ hilorrk:大小可言...要說的話 說是零或大小不定都對 11/03 00:32
推 tropical72:先謝謝h大補充,但不知是不是vc關係,上述是 error C2149 11/03 01:17
推 tropical72:sori! 請無視樓上,可過(4bytes),have a warnning. 11/03 01:22
推 cobrasgo:好強大… 11/03 03:14