接前面C/Cpp strict alias小结,看一些与此相关的例子:
例子一
测试环境:gcc-4.4(ubuntu x86),gcc-4.4(mingw32)
结果:
编译用命令及选项 | 结果 |
gcc -Wall hello.c | 0 |
gcc -Wall -O3 hello.c | 1 |
代码:
#include <stdio.h> int a; int f(float *b) { a = 1; *b = 0; return a; } int main() { printf("%d\n", f((float*)&a)); return 0; }
例子二
测试环境:gcc-4.4/4.5(ubuntu x86),gcc-4.4(mingw32)
编译用命令及选项 | 结果 |
gcc -Wall hello.c | 65535 |
gcc -Wall -O3 hello.c | 42 |
代码:
#include <stdio.h> int main() { void *buf[4]; int *i = (int *) buf; short *s = (short *) buf; *i = 42; s[0] = 0; s[1] = 1; printf("%d\n", *i); return 0; }
例子三
按照我们在上一篇提到的内容,这个例子的结果在C语言中应该是可预知的(由实现定义?),而在C++中的行为可能是未定义的。
而type-punning-and-strict-aliasing一文中,提到:这个例子的结果在gcc下面是1,在其他编译器下则不尽然。(我尝试重现这个东西,却总是不成功,估计是Thiago在这儿弄错了,简化得太厉害了?)
测试环境:
- gcc4.4/4.5(Ubuntu X86)
- gcc4.4(mingw32)
- visual studio 2010, X86
- clang 2.8 (Ubuntu X86)
- Sun studio 11 (X4100/Solaris,x86)
- gcc3.4 (X4100/Solaris,x86)
- Sun studio 11 (T1000/Solaris,Sparc)
- gcc4.0 (T1000/Solaris,Sparc)
结果(只看到大小端的区别):
T1000/Solaris,Sparc | 65578 | 大端 |
其他平台 | 1 | 小端 |
代码:
#include <stdio.h> int main() { union { int i; short s; } u; u.i = 42; u.s = 1; printf("%d\n", u.i); return 0; }
例子四
(Ab)Use of the ANSI C aliasing rules 给出这样一段代码:
/*alias.c*/ int foo(char *c) { char a[100]; char *cptr = a; *(int *)cptr = *(int*)c; return 0; }
使用IBM的 xlc 编译器
xlc -c alias.c -O3 -qlist=./ -qflag=i -qinfo
可以看到如下警告信息
INFORMATIONAL CCN3495 ./alias.c:5 Pointer type conversion found. INFORMATIONAL CCN3374 ./alias.c:5 Pointer types "int*" and "char*" are not compatible. INFORMATIONAL CCN3495 ./alias.c:5 Pointer type conversion found. INFORMATIONAL CCN3374 ./alias.c:5 Pointer types "int*" and "char*" are not compatible. INFORMATIONAL CCN3415 ./alias.c:7 The external function definition "foo" is never referenced.
没有这种环境,无法测试,而且 http://www.unix-center.net 提供的 IBM UNIX eServer p510 服务最近无法登录。
例子五
Visual Studio .NET 2003 存在 /Oa 和 /Ow 两个和 alias 有关的优化选项,不过从 VS2005 开始,似乎这两个选项消失了。
MSDN VS2003 中说:
- The following code can cause an aliasing problem:
i = -100; while( i < 0 ) { i += x + y; *p = i; }
不过,这个和 strict alias 应该没多少关系。