《C++ 對象模型》第19頁有這樣一句話
C程序員的巧計有時候卻成為c++程序員的陷阱。例如把單一元素的數組放在一個struct的末尾,于是每個struct objects可以擁有可變數組的數組:
struct mumble
{/* stuff */char pc[1];
};//從文件或標準輸入裝置中取得一個字符串
//然后為struct 本身和該字符配置足夠的內存struct mumble * pmumbl = (struct mumble*)malloc(sizeof(struct mumble) + strlen(string) +1);
strcpy(&mumble.pc,string);
正好之前看MCP++的cache acess組件的時候也發現THashMap等結構體在結構體末尾使用了單一元素的數組,說明這一技巧確實用的廣泛,現在看看其原理:
結構體的末尾定義了一個char數組,只分配了1個字符。那怎么能說是可變大小數組。
malloc函數分配了一堆的內存。大小為結構體+字符串+1(字符串結束符)
指針pmumbl指向的是malloc所分配的整個內存,而pmumbl->pc指向的是這塊內存的第一個字節,因為malloc操作為整個string分配了足夠的內存,所以在strcpy的時候,雖然溢出了pc的內存范圍,但沒有溢出struct的內存范圍,使得strcpy的結果就是合理的且可控的。相當于struct擁有了可變大小的數組
C++中 public、protected、private內的聲明順序可以被保證,但是這三個關鍵字的布局是不同的。因此總的排列順序并不能被保證。因此,不一定能實現struct的可變大小的數組,建議是不要那么做。
下面看一下代碼驗證:
#include <iostream>
#include <string.h>
using namespace std;typedef struct mumble
{/* stuff */char pc[1];
} mumble;
int main(int argc, char **argv){mumble raw;raw.pc[0] = 'a';cout << "raw " << sizeof(raw) << endl;char str[10] = "abcdefgxa";mumble* mumptr = (mumble*)malloc(sizeof(mumble) + strlen(str));strcpy_s(mumptr->pc,strlen(str) + 1, str);cout << "mumptr " << sizeof(*mumptr) << endl;cout << mumptr->pc << endl;free(mumptr);
}
打印結果:sizeof并不能獲取mumptr的真實大小,但是通過下標訪問確實能夠訪問到pc
raw 1
mumptr 1
abcdefgxa
內存分布圖:
會發現內存中確實有值:
所以以后定義可變包結構時候,結構中沒有可變包的大小,而是只要在結構里最后加一個元素的字節數組就可以。
參考:
https://blog.csdn.net/qq_35749455/article/details/116356006
https://blog.csdn.net/weixin_30855761/article/details/99864866?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-3.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-3.pc_relevant_default&utm_relevant_index=5