超出结构的一个元素来查看另一个元素是否合法?

时间:2011-12-13 14:35:16

标签: c++ c standards

鉴于以下设计的示例代码:

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,是否有一个实例,这将是“非法的”(即写入内存我不“拥有”)?

4 个答案:

答案 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)

从技术上讲,行为是未定义的。

  

虽然不是最好的编程习惯,但确实有效。

未定义的行为意味着任何事情都可能发生,包括您的期望。它可能会在其他实现上崩溃。