你的关于“为什么不使用大小为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