在gcc-strict-aliasing-and-casting-through-a-union 中,我询问是否有人遇到过通过指针进行联合双关的问题。到目前为止,答案似乎是否定的。
这个问题更广泛:你有任何关于 gcc 和严格混叠的恐怖故事吗?
背景:引用AndreyT 在 c99-strict-aliasing-rules-in-c-gcc 中的回答:
“严格的别名规则植根于自 [标准化] 时代开始以来存在于 C 和 C++ 中的部分标准。禁止通过另一种类型的左值访问一种类型的对象的条款存在于 C89/90 (6.3 ) 以及在 C++98 (3.10/15) 中......只是并非所有编译器都想要(或敢于)强制执行或依赖它。”
好吧,gcc现在敢于这样做了,它的-fstrict-aliasing
switch。这引起了一些问题。例如,参见关于 Mysql 错误的优秀文章 http://davmac.wordpress.com/2009/10/ ,以及http://cellperformance.beyond3d.com/articles/2006/06/understanding中同样出色的讨论-strict-aliasing.html。
其他一些不太相关的链接:
再说一遍,你有自己的恐怖故事吗?当然,未指出的问题将是首选。-Wstrict-aliasing
也欢迎其他 C 编译器。
6 月 2 日添加: Michael Burr 的回答中的第一个链接,确实符合恐怖故事的条件,可能有点过时(从 2003 年开始)。我做了一个快速测试,但问题显然已经消失了。
资源:
#include <string.h>
struct iw_event { /* dummy! */
int len;
};
char *iwe_stream_add_event(
char *stream, /* Stream of events */
char *ends, /* End of stream */
struct iw_event *iwe, /* Payload */
int event_len) /* Real size of payload */
{
/* Check if it's possible */
if ((stream + event_len) < ends) {
iwe->len = event_len;
memcpy(stream, (char *) iwe, event_len);
stream += event_len;
}
return stream;
}
具体投诉如下:
一些用户抱怨说,当 [above] 代码在没有 -fno-strict-aliasing 的情况下编译时,write 和 memcpy 的顺序是相反的(这意味着一个虚假的 len 被 mem 复制到流中)。
编译代码,在 CYGWIN 上使用gcc 4.3.4 和 -O3 (如果我错了,请纠正我——我的汇编器有点生疏了!):
_iwe_stream_add_event:
pushl %ebp
movl %esp, %ebp
pushl %ebx
subl $20, %esp
movl 8(%ebp), %eax # stream --> %eax
movl 20(%ebp), %edx # event_len --> %edx
leal (%eax,%edx), %ebx # sum --> %ebx
cmpl 12(%ebp), %ebx # compare sum with ends
jae L2
movl 16(%ebp), %ecx # iwe --> %ecx
movl %edx, (%ecx) # event_len --> iwe->len (!!)
movl %edx, 8(%esp) # event_len --> stack
movl %ecx, 4(%esp) # iwe --> stack
movl %eax, (%esp) # stream --> stack
call _memcpy
movl %ebx, %eax # sum --> retval
L2:
addl $20, %esp
popl %ebx
leave
ret
对于迈克尔回答中的第二个链接,
*(unsigned short *)&a = 4;
gcc通常(总是?)会发出警告。但我相信一个有效的解决方案(对于gcc)是使用:
#define CAST(type, x) (((union {typeof(x) src; type dst;}*)&(x))->dst)
// ...
CAST(unsigned short, a) = 4;
我已经问过这在gcc-strict-aliasing-and-casting-through-a-union中是否可行,但到目前为止没有人不同意。