协慌网

登录 贡献 社区

以每种语言编译时,在 C 和 C ++ 中都有效的代码能否产生不同的行为?

C 和 C ++ 有很多区别,并且并非所有有效的 C 代码都是有效的 C ++ 代码。
(“有效” 是指具有定义行为的标准代码,即不是特定于实现的 / 未定义的等。)

在任何情况下,使用每种语言的标准编译器进行编译时,在 C 和 C ++ 中都有效的一段代码会产生不同的行为吗?

为了进行合理 / 有用的比较(我试图学习一些实用的东西,而不是试图在问题中发现明显的漏洞),让我们假设:

  • 与预处理器无关(这意味着没有使用#ifdef __cplusplus ,pragmas 等的黑客行为)
  • 实现定义的任何内容在两种语言中都是相同的(例如,数值限制等)
  • 我们正在比较每个标准的合理最新版本(例如 C ++ 98 和 C90 或更高版本)
    如果版本很重要,请说明每个版本产生不同的行为。

答案

这是一个利用 C 和 C ++ 中的函数调用和对象声明之间的区别以及 C90 允许调用未声明函数的事实的示例:

#include <stdio.h>

struct f { int x; };

int main() {
    f();
}

int f() {
    return printf("hello");
}

在 C ++ 中,这不会打印任何内容,因为f ;但是在 C90 中,它将打印出hello因为无需声明即可调用函数。

如果您想知道名称f被两次使用,C 和 C ++ 标准明确允许这样做,并且要创建一个对象,您必须说struct f消除歧义(如果您想要结构),或者省略struct如果想要功能) 。

对于 C ++ 和 C90,至少存在一种获得未定义实现的不同行为的方法。 C90 没有单行注释。稍加注意,我们就可以使用它来创建一个在 C90 和 C ++ 中具有完全不同结果的表达式。

int a = 10 //* comment */ 2 
        + 3;

在 C ++ 中,从//到该行的末尾的所有内容均为注释,因此其结果为:

int a = 10 + 3;

由于 C90 没有单行注释,因此只有/* comment */是注释。第一个/2都是初始化的一部分,因此可以得出:

int a = 10 / 2 + 3;

因此,一个正确的 C ++ 编译器将提供 13,但一个完全正确的 C90 编译器将给 8。

以下内容(在 C 和 C ++ 中有效)将(最有可能)在 C 和 C ++ i

int i = sizeof('a');

有关差异的说明,请参见C / C ++ 中的字符大小('a')。

本文中的另一篇文章:

#include <stdio.h>

int  sz = 80;

int main(void)
{
    struct sz { char c; };

    int val = sizeof(sz);      // sizeof(int) in C,
                               // sizeof(struct sz) in C++
    printf("%d\n", val);
    return 0;
}