关于什么是"未定义的行为",什么不是,在 comments 中似乎有很多混淆之处,所以让我一行行地介绍一下:
BIGWORD* bwBufferCast = (BIGWORD*)cBuffer;
This is valid C since all manner of wild and crazy pointer casts are allowed in C (C17 6.3.2.3 §7).
但是,此指针转换在某些情况下可能会调用未定义的行为,因为您开始的字符数组可能不对齐,并且 struct 类型可能有对齐要求.如果发生这种情况,一些CPU可能会在指针分配本身上设置指令trap .在其他CPU上,稍后在取消引用指针时可能会遇到问题.
(BIGWORD*) { "I am trying to copy this whole text inside a buffer!" };
This is invalid C and will not compile cleanly. You create a compound literal consisting of a pointer. Initialization of that pointer (a so-called scalar) is done "as if by assignment" (C17 6.7.9 §11). Specifically, you are trying to initialize a BIGWORD*
with a char*
.
然后我们可以判断有效赋值的规则(C17 6.5.16.1),并发现对于在赋值期间允许的隐式指针转换,指针需要兼容.它们不是(C17 6.2.7),所以这是违反约束的,编译器必须发出诊断.
违反约束仍然会导致二进制可执行文件的程序是不符合C语言的,并且标准对任何行为都没有保证.
*(BIGWORD*)
是可疑的.同样存在前面提到的潜在对齐问题,如果 struct 的字符串文字没有对齐,这将是未定义的行为.
但也很可疑,因为您使用与声明的有效类型不同的类型对对象进行左值访问.正常情况下,我们可能会将其称为所谓的"严格混叠违规",What is the strict aliasing rule?.Tl;dr违反类型系统规则,导致未定义的行为.这可能会导致编译器生成错误的代码.
但碰巧的是,这一行是一个严格的别名违规,因为(幸运的是)您设法满足了该规则的一个例外(C16 6.5§7).我们有一个 struct ,一个聚合类型,但有一个例外:"在其成员中包含上述类型之一的聚合或联合类型".其中"上述类型"包括"与对象的有效类型相对应的有符号类型或无符号类型的类型".成员为unsigned char[]
的 struct 是与对象的有效类型char[]
相对应的无符号类型.
这里有*bwBufferCast
个和上面一样的问题.潜在的错位,可疑但不严格的混叠违规.
结论:
这个程序不能很好地工作,因为它不能编译.使用一致的编译器(GCC 13.3-std=c17 -pedantic-errors
),我得到预期的诊断消息:
错误:从不兼容的指针类型‘char*’初始化‘BIGWORD*’{AKA‘STRUCT_BIGWORD*’}[-WinCompatible-POINTER-TYPE]
如果您无论如何都运行了可执行文件,并且它没有因未对齐而出错,那么您可能仍然会得到预期的结果,要么是运气不好,要么是通过编译器扩展得到的保证.
还请注意,"我只得到了一个警告"仍然意味着程序可能是无效的C,没有保证的行为.退房What must a C compiler do when it finds an error?英镑