Re: [問題] 請問array size奇怪定義

看板C_and_CPP作者 (可愛中央處理器)時間14年前 (2011/11/02 16:23), 編輯推噓8(807)
留言15則, 7人參與, 最新討論串2/2 (看更多)
※ 引述《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

11/02 16:55, , 1F
樓上是神
11/02 16:55, 1F

11/02 17:01, , 2F
話說這讓我想到 VC2005 的 _countof... (ref.#18GQ0GzF)
11/02 17:01, 2F

11/02 17:02, , 3F
那個用的方法需要一點 template 的概念才看得懂 XD"
11/02 17:02, 3F

11/02 19:30, , 4F
static assertion?
11/02 19:30, 4F

11/02 20:53, , 5F
之前沒發現的現象 http://boost.codepad.org/93baR82G XD
11/02 20:53, 5F

11/02 21:38, , 6F
cool!
11/02 21:38, 6F

11/02 23:09, , 7F
推, 太強大了Orz
11/02 23:09, 7F

11/02 23:31, , 8F
cutecpu 好強!! 補一下, struct {int:0;} 大小應不是
11/02 23:31, 8F

11/02 23:31, , 9F
確定的,depends on compiler ?
11/02 23:31, 9F

11/03 00:29, , 10F
「大小不確定」的說法不太正確,因為0-width bit-field是
11/03 00:29, 10F

11/03 00:31, , 11F
align,由於它一定是unnamed(沒有declarator) 所以也沒有
11/03 00:31, 11F

11/03 00:32, , 12F
大小可言...要說的話 說是零或大小不定都對
11/03 00:32, 12F

11/03 01:17, , 13F
先謝謝h大補充,但不知是不是vc關係,上述是 error C2149
11/03 01:17, 13F

11/03 01:22, , 14F
sori! 請無視樓上,可過(4bytes),have a warnning.
11/03 01:22, 14F

11/03 03:14, , 15F
好強大…
11/03 03:14, 15F
文章代碼(AID): #1EiFty_y (C_and_CPP)
文章代碼(AID): #1EiFty_y (C_and_CPP)