你的關於「爲什麼不使用大小爲1的數組」的說法是現貨。
該代碼正在執行「C struct hack」錯誤,因爲零長度數組的聲明是違反約束的。這意味着編譯器可以在編譯時立即拒絕你的黑客攻擊,並帶有停止翻譯的診斷消息。
如果我們想進行黑客攻擊,我們必須偷偷通過編譯器。
做了「C結構黑客」(這是一個用C方言追溯到1989 ANSI C,而且可能更早兼容)是用大小爲1的完全有效的陣列正確的做法:
struct someData
{
int nData;
unsigned char byData[1];
}
此外,代替sizeof struct someData
,零件的byData
之前的大小,使用計算:
offsetof(struct someData, byData);
要byData
與空間分配struct someData
爲42個字節,我們再使用:
struct someData *psd = (struct someData *) malloc(offsetof(struct someData, byData) + 42);
請注意,即使在數組大小爲零的情況下,該計算實際上也是正確的計算。你看,sizeof
整個結構可以包含填充。舉例來說,如果我們有這樣的事情:
struct hack {
unsigned long ul;
char c;
char foo[0]; /* assuming our compiler accepts this nonsense */
};
的struct hack
的大小是因爲ul
成員的排列很可能填充。如果unsigned long
是四個字節寬,那麼很可能是sizeof (struct hack)
是8,而offsetof(struct hack, foo)
幾乎肯定是5. offsetof
方法是在數組之前獲得結構的前一部分的準確大小的方式。
因此,這將是重構代碼的方式:使其符合經典,高度可移植的結構破解。
爲什麼不使用指針?因爲指針佔用額外的空間並且必須被初始化。
還有其他很好的理由不使用指針,即指針需要地址空間纔能有意義。 struct hack是可以外部化的:也就是說,在某些情況下,這樣的佈局符合外部存儲,比如文件,數據包或共享內存區域,因爲它們沒有意義,所以不需要指針。
幾年前,我在內核和用戶空間之間的共享內存消息傳遞接口中使用了struct hack。我不想要指針,因爲它們只對生成消息的進程的原始地址空間有意義。軟件的內核部分使用其自己的映射在不同地址的內存視圖,因此所有內容都基於偏移量計算。
來源
2014-05-21 06:39:50
Kaz
這是[comp.lang.c FAQ](http://www.c-faq.com/)問題2.6中描述的「struct hack」。 Dennis Ritchie稱之爲「C實施中的無端愚蠢」。 C99引入了一種新的語言特性,即「靈活的數組成員」,以替代struct hack。即使是微軟的編譯器,它缺乏C99支持,也支持靈活的陣列成員。 – 2012-09-11 18:37:11
請勿將`c`標籤添加到此問題中。C++規則與C規則完全不同。 – 2014-05-21 06:03:52
@BenVoigt接受的答案是純粹的C代碼,所以我想你的編輯是錯誤的。 c hack以同樣的方式適用於c和C++ – 2014-05-21 06:14:23