我们知道什么是未定义行为并且我们(或多或少)知道其中大部分的原因(性能、跨平台兼容性)。假设一个给定的平台,比如 Windows 32 位,我们是否可以将未定义的行为视为众所周知并且在整个平台上保持一致?我知道没有一个通用的答案然后我会限制为两个常见的 UB我在生产代码中经常看到(多年来一直在使用)。
1) Reference 。给出这个 union
:
union {
int value;
unsigned char bytes[sizeof(int)];
} test;
像这样初始化:
test.value = 0x12345678;
然后访问:
for (int i=0; i < sizeof(test.bytes); ++i)
printf("%d\n", test.bytes[i]);
2) Reference 。给定一个无符号数组 short*
转换为(例如)float*
并访问它( reference ,数组成员之间没有填充)。
代码是否依赖于众所周知的 UB(如那些)按情况工作(假设编译器可能会改变并且肯定编译器版本会肯定会改变)或者即使他们是跨平台代码的 UB,他们依赖于平台特定的细节(如果我们不改变平台,它就不会改变)?同样的推理是否也适用于未指定行为(当编译器文档没有说明任何相关内容时)?
编辑 根据 this post 从 C99 开始类型双关只是未指定,而不是未定义。
最佳答案
未定义的行为主要意味着一件非常简单的事情,相关代码的行为未定义,因此 C 标准不提供任何可能发生的线索。不要在其中搜索更多内容。
如果 C 标准没有定义某些东西,您的平台很可能会作为扩展来定义。所以如果你是这种情况,你可以在那个平台上使用它。但是请确保他们记录了该扩展,并且他们不会在您的编译器的下一个版本中更改它。
由于多种原因,您的示例存在缺陷。正如评论中所讨论的那样,union
是为类型双关而设计的,特别是对内存的访问,因为任何字符类型总是被允许的。你的第二个例子真的很糟糕,因为除了你似乎暗示的之外,这在我所知道的任何平台上都是 Not Acceptable 。 short
和 float
通常具有不同的对齐属性,使用这样的东西几乎肯定会使您的程序崩溃。然后,第三,您在 Windows 上争论 C,这是众所周知的事实,因为它们不遵循 C 标准。
关于c - 什么时候未定义的行为可以被认为是众所周知的并被接受?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27422334/