Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 超越结构的一个元素以查看另一个元素是否合法?_C++_C_Standards - Fatal编程技术网

C++ 超越结构的一个元素以查看另一个元素是否合法?

C++ 超越结构的一个元素以查看另一个元素是否合法?,c++,c,standards,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,是否有过这样的情况“非法”(即写入我不“拥有”的内存)?从技术上

给出以下人为的示例代码:

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,是否有过这样的情况“非法”(即写入我不“拥有”的内存)?

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

虽然这不是最好的编程实践,但确实有效


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

不,它既不合法,也不能保证有效。编译器可以向结构中添加填充,以帮助对齐,具体取决于体系结构等

编辑:总结这些评论中的一些内容并澄清

我确实相信您“拥有”了那里的内存,因为正如edA qa mort-ora-y所指出的,结构的memcpy()需要/有望工作。但我不确定这是否有明确的保证


也就是说,未定义的行为是要不惜一切代价避免的。具有未定义行为的程序所做的事情可能会在相隔五秒钟的两次单独运行相同代码之间发生变化。它可能会导致程序中出现细微的内存损坏、segfault或运行正常,但没有理由使用依赖于未定义行为的代码。

这是未定义行为-在这种情况下,您(未)幸运。此外(除了提到的填充问题外),还有可维护性问题——它非常脆弱——如果有人在两者之间插入其他东西会怎么样。我确信这是一个人为的例子,但建议是——不要这样做。

编辑:正如其他人所指出的,这是不合法的,因为它会导致未定义的行为。我已经把这句话从我的回答中删去了

这有可能导致未定义的行为。您已经在结构abc中分配了一个长度为10整数的内存块,因此索引到第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位进行位压缩,以保持变量之间的标准偏移量

当您在两个不同的位置声明一个结构时,由于编译时选项或配置的原因,其中一个得到位压缩,而另一个没有得到位压缩,这可能会非常混乱


查看位打包和数据对齐或位对齐以了解更多信息。

如果您尝试使用
char
而不是
int
,并保持数组的奇数大小,则很有可能相同的代码会中断。
void main()是无效的C或C++。让我问另一个问题:为什么你会认为你需要做这样的事情?@ KeRekSB:但是,很多很多嵌入式环境都希望有一个<代码>空洞主(空)。
其中,
main
的返回值没有意义,因为程序启动后将无限期运行。@Pubby:您对“合法”(“不会让您入狱”?)的定义是什么?我确实“拥有”整个内存块,对吗?i、 e.写
test.x[5]=10并不违法,即使不能保证值会出现在
test.y[0]
?我试图区分合法的和非常非常糟糕的想法。@davidfeffer:这里的意思是,即使你拥有内存块,也不能保证你会用这个技巧读到什么。@davidfeffer:它不一定会导致错误。任何事情都有可能发生。这就是未定义行为的含义,这就是为什么您应该避免它。我不再认为在C++11中这是未定义行为。这是一种标准布局类型,这意味着定义了通过memcpy进行复制,因此必须保证填充空间中的内存。虽然我完全同意这个值是未定义的,并且不能保证会转到下一个成员。但由于标准的布局要求,访问内存必须是安全的。比潜在的“崩溃”更重要(也是更令人信服的论据)事实上,编译器在优化您违反的代码时可能会对您的代码做出假设。@davidfeffer:我不确定接受唯一没有提到“未定义行为”的答案是否正确。当然,这似乎是在安慰你的信仰,但你真的不应该这么做。这是不合法的,从某种意义上说,它给出了未定义的行为。换言之:
这是合法的,因为它给出了未定义的行为,并且可能会打印所有内容
——在我的书中,这与合法完全相反。我编辑了我的答案,以反映这样一个事实:这确实是非法的,因为它导致了未定义的行为。C++11标准几乎不用“合法”这个词,也没有定义它。在它确实使用它的任何情况下(我可以找到),它描述为“非法”的东西被编译器拒绝,或者它描述为“合法”的东西被接受并定义了行为。所以,选择你认为应该是什么意思,但优先使用标准术语(“格式良好”、“格式不良”、“UB”)