鉴于以下设计的示例代码:
struct abc
{
int x[5];
int y[5];
};
void main()
{
struct abc test;
test.y[0] = 10;
printf("%n", test.x[5]);
}
该程序的输出为10。
虽然不是最好的编程实践,但这确实有效。但是,这是编译器和平台的工件,还是这个合法代码? (即由C标准定义?)
即使结果不能保证为10,是否有一个实例,这将是“非法的”(即写入内存我不“拥有”)?
答案 0 :(得分:12)
不,这不合法也不保证可行。编译器可以在结构中添加填充,以帮助对齐,具体取决于体系结构等。
编辑:总结一下这些评论中的一些内容并澄清......
我确实相信你“拥有”那里的记忆,因为正如edA-qa mort-ora-y指出的那样,结构的memcpy()需要/有望起作用。虽然这是特别保证的,但我不确定。
话虽这么说,未定义的行为是不惜一切代价避免的。具有未定义行为的程序可能会在相隔5秒的相同代码的两次单独运行之间发生变化。它可能会导致程序中的细微内存损坏,段错误或运行正常,但没有理由使用依赖于未定义行为的代码。
答案 1 :(得分:5)
这是未定义的行为 - 在这种情况下你是(非)幸运的。更进一步(除了上面提到的填充问题),存在可维护性问题 - 它非常脆弱 - 如果有人在其他方面粘贴其他内容会怎么样。我确信这是一个人为的例子,但建议是 - 不要这样做。
答案 2 :(得分:4)
这有可能导致未定义的行为。你已经在struct abc中分配了一个10 int整数的内存块,所以索引到第5个(第6个)项将带你到y [0],正如你在这个特定情况下所说的那样。
当遇到问题时,C编译器会以您不期望的方式打包结构。这称为数据打包或位对齐。当计算机想要从您的数据结构访问内存时,它将尝试以统一的块为整个结构执行此操作。我们来举个例子:
struct abc {
int a;
char b;
int c;
};
您期望这个结构的大小是什么? int是32位,char是8位,因此总大小应该是32 + 8 + 32 = 72位。但是,您会发现在许多系统上,此结构实际上是96位大小。原因是char b在最后添加了24位,以保持变量之间的标准偏移。
当你在两个不同的地方声明一个结构时,这可能会非常混乱,一个得到点打包而另一个不是由于编译时选项或配置。
查找位打包和数据对齐或位对齐以获取更多信息。
答案 3 :(得分:3)
从技术上讲,行为是未定义的。
虽然不是最好的编程习惯,但确实有效。
未定义的行为意味着任何事情都可能发生,包括您的期望。它可能会在其他实现上崩溃。