《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