繁体   English   中英

为什么在使用gcc和g ++编译时,以下代码会给出不同的结果?

[英]Why does the following code give different results when compiling with gcc and g++?

#include<stdio.h>
int main()
{
    const int a=1;
    int *p=(int *)&a;
    (*p)++;
    printf("%d %d\n",*p,a);
    if(a==1)
      printf("No\n");//"No" in g++.
    else
      printf("Yes\n");//"Yes" in gcc.
    return 0;
}

上面的代码在g++编译中给出No作为输出,在gcc编译中给出Yes 任何人都能解释一下这背后的原因吗?

您的代码会触发未定义的行为,因为您正在修改const对象( a )。 它不必产生任何特定的结果,即使在相同的平台上,也不必使用相同的编译器。

虽然没有指定此行为的确切机制,但您可以通过检查代码生成的程序集来弄清楚您的特定情况下发生了什么(您可以通过使用-S标志来查看。)请注意编译器允许通过假定具有明确定义的行为的代码来进行积极的优化。 举例来说, a可以简单地通过更换1无论在何处使用。

来自C ++标准(1.9程序执行)

4本国际标准中将某些其他操作描述为未定义( 例如,尝试修改const对象的效果 )。 [注意:本国际标准对包含未定义行为的程序的行为没有要求。 - 尾注]

因此,您的程序具有未定义的行为。

在您的代码中,请注意以下两行

const int a=1;        // a is of type constant int
int *p=(int *)&a;     // p is of type int *

您将const int变量的地址放入int * ,然后尝试修改该值,该值应该被视为const 这是不允许的,并调用未定义的行为

供参考,如第6.7.3章, C11标准第6段所述

如果尝试通过使用具有非const -qualified类型的左值来修改使用const -qualified类型定义的对象,则行为是未定义的。 如果尝试通过使用具有非volatile限定类型的左值来引用使用volatile限定类型定义的对象,则行为未定义

因此,长话短说,你不能依靠comaprison的输出。 它们是未定义行为的结果。

好的,我们这里的“相同”代码传递给“相同”的编译器,但一次带有C标志,另一次带有C ++标志。 就任何合理的用户而言,没有任何改变。 代码应该由编译器完全相同地解释,因为没有发生任何重大事件。

实际上,那不是真的。 虽然我很难在标准中指出它,但对'const'的精确解释在C和C ++之间略有不同。 在C中它是一个附加组件,'const'标志表示这个常规变量'a'不应该由这里的代码写入。 但它有可能被写入其他地方。 对于C ++,重点更多地放在不可变常量概念上,编译器知道这个常量更类似于普通变量的“枚举”。

所以我希望这种微小的差异意味着生成稍微不同的解析树,最终导致不同的汇编程序。

这种事情实际上是相当常见的,即使使用“相同的”编译器,C / C ++子集中的代码也不总是编译为完全相同的汇编程序。 它往往是由其他语言特性引起的,这意味着有些东西你现在无法在其中一种语言中证明代码,但在另一种语言中它是可以的。

通常C是性能优胜者(由Linux内核开发人员重新发现),因为它是一种更简单的语言,但在这个例子中,C ++可能会变得更快(除非C dev切换到宏或枚举并捕获不合理的行为)获取不可变常量的地址)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM