在gcc-strict-aliasing-and-casting-through-a-union年,我问过是否有人遇到过unions 通过指针双关语的问题.到目前为止,答案似乎是No.
这个问题更广泛:你有any个关于gcc和严格别名的恐怖故事吗?
背景资料:引述自AndreyT's answer in 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中同样优秀的讨论.
其他一些不太相关的链接:
- performance-impact-of-fno-strict-aliasing个
- strict-aliasing
- when-is-char-safe-for-strict-pointer-aliasing个
- how-to-detect-strict-aliasing-at-compile-time个
再说一遍,你有自己的恐怖故事吗?当然,以-Wstrict-aliasing
表示的问题not将是首选.和其他C编译器也很受欢迎.
Added June 2nd:Michael Burr's answer中的第一个链接,indeed符合恐怖故事的条件,可能有点过时了(从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;
}
具体投诉如下:
一些用户抱怨说,当编译[上述]代码时没有-fno严格的别名,写入和memcpy的顺序是颠倒的(这意味着伪len是mem复制到流中的).
编译代码,在CYGWIN with h-O3上使用gcc 4.3.4(如果我错了,请纠正我--我的汇编器有点Rust 了!):
_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通常(总是?)给个警告.但I believe对此(对于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年后这是否可以,但到目前为止没有人不同意.