g++和gcc编译c程序结果不一样

发布于 2022-08-31 20:19:16 字数 353 浏览 19 评论 0

就是下面的代码:

#include<stdio.h>

void swap(int *a, int *b)
{
    *a ^= *b ^= *a ^= *b;
}

int main()
{
    int a = 100, b = 1;
    swap(&a, &b);
    printf("%d   %d\n", a, b);
    return 0;
}

我使用gcc编译出来结果是0 100,
但是使用g++编译出来是1 100。
嗯,gcc版本gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) 。。谢谢各位

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

记忆消瘦 2022-09-07 20:19:16

可以参考C标准中关于sequence point的描述。
用gcc编译时加上警告选项-Wsequence-point,就比较明显了。

$ gcc -o swap swap.c -Wsequence-point
swap.c: In function ‘swap’:
swap.c:5:5: warning: operation on ‘*a’ may be undefined [-Wsequence-point]
  *a ^= *b ^= *a ^= *b;
     ^

在C中,()、;、&&、||等等这样的地方是sequence-point。两个sequence-point之间的代码,编译器是可以任意优化的。也就是说,*a ^= *b ^= *a ^= *b;的计算顺序是未定义的。

C++对sequence point的规定与C基本一致,*a ^= *b ^= *a ^= *b;的行为同样是未定义的。另外因为C++规定赋值语句的结果是左值,对这结果也可能会有影响。

总之有side effect的写法还是尽量不要用。

装纯掩盖桑 2022-09-07 20:19:16

第一 g++编译.c文件实际上也就是把c源文件当c++源文件编译。
第二 这段代码本来就是有歧义的,处理的顺序不同也就结果不同。编译器有时候特定的处理顺序经常会出现这种情况。

不过clang/clang++编译的结果都是 1 100

囚你心 2022-09-07 20:19:16

恭喜你,你触发了一个未定义行为!

swap函数中,符号执行的顺序是未定义的,不同编译器编译的结果会不一样。

# 把代码保存为test.c
gcc -S -g -o test.s test.c # 输出汇编文件test.s
g++ -S -g -o test2.s test.c
vimdiff test.s test2.s # diff不同的输出

可以看出gcc和g++编译出的汇编码是不一样的,两者中xor的应用对象不一样。

BTW,在异或交换之前,需要检查a和b是不是同一个对象,否则会产生糟糕的问题。

凝望流年 2022-09-07 20:19:16
 *a ^= *b ^= *a ^= *b;//这种编码风格是极不推荐的,或者说是禁止的.正确方法是把每一步写成一行,自己看得舒服,编译器也能正确编译.减小代码量的意思不是说用你的这种抠门方法
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文