C和c++有很多不同之处,并不是所有有效的C代码都是有效的c++代码。 (这里的“有效”指的是具有定义行为的标准代码,即不是特定于实现的/未定义的/等等。)

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

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

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


当前回答

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

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

在c++中,从//到行尾的所有内容都是注释,所以这是:

int a = 10 + 3;

因为C90没有单行注释,所以只有/*注释*/是注释。第一个/和2都是初始化的一部分,所以结果是:

int a = 10 / 2 + 3;

因此,正确的c++编译器会给出13,而严格正确的C90编译器会给出8。当然,这里我只是随便选了几个数字,你也可以用其他合适的数字。

其他回答

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

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

在c++中,从//到行尾的所有内容都是注释,所以这是:

int a = 10 + 3;

因为C90没有单行注释,所以只有/*注释*/是注释。第一个/和2都是初始化的一部分,所以结果是:

int a = 10 / 2 + 3;

因此,正确的c++编译器会给出13,而严格正确的C90编译器会给出8。当然,这里我只是随便选了几个数字,你也可以用其他合适的数字。

下面是一个例子,它利用了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。

#include <stdio.h>

struct A {
    double a[32];
};

int main() {
    struct B {
        struct A {
            short a, b;
        } a;
    };
    printf("%d\n", sizeof(struct A));
    return 0;
}

这个程序在使用c++编译器编译时输出128 (32 * sizeof(double)),在使用C编译器编译时输出4。

这是因为C语言没有范围解析的概念。在C语言中,包含在其他结构中的结构被放到外部结构的范围内。

一个依赖于C编译器的老栗子,不识别c++的行尾注释……

...
int a = 4 //* */ 2
        +2;
printf("%i\n",a);
...

C中的内联函数默认为外部作用域,而c++中的内联函数则不是。

在GNU C中,将下面两个文件编译在一起将打印“I am inline”,而在c++中则没有。

文件1

#include <stdio.h>

struct fun{};

int main()
{
    fun();  // In C, this calls the inline function from file 2 where as in C++
            // this would create a variable of struct fun
    return 0;
}

文件2

#include <stdio.h>
inline void fun(void)
{
    printf("I am inline\n");
} 

此外,c++隐式地将任何const全局变量视为静态的,除非显式地声明了extern,不像C中extern是默认值。