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

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

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

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


当前回答

struct abort
{
    int x;
};

int main()
{
    abort();
    return 0;
}

在c++中返回退出码为0,在C中返回退出码为3。

这个技巧可能可以用来做一些更有趣的事情,但我想不出一个好方法来创建一个构造函数,让c满意。我试着用复制构造函数做了一个同样无聊的例子,让一个参数被传递,尽管以一种相当不可移植的方式:

struct exit
{
    int x;
};

int main()
{
    struct exit code;
    code.x=1;

    exit(code);

    return 0;
}

vc++ 2005拒绝在c++模式下编译,但是,抱怨如何重新定义“退出代码”。(我认为这是一个编译器错误,除非我突然忘记了如何编程。)但是当它被编译成C语言时,进程退出码为1。

其他回答

以下语句在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;
}

下面是一个例子,它利用了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语言中,包含在其他结构中的结构被放到外部结构的范围内。

C90 vs. c++ 11 (int vs. double)

#include <stdio.h>

int main()
{
  auto j = 1.5;
  printf("%d", (int)sizeof(j));
  return 0;
}

在C语言中,auto表示局部变量。在C90中,可以省略变量或函数类型。它默认为int。在c++ 11中,auto的意思完全不同,它告诉编译器从用于初始化变量的值推断变量的类型。

不要忘记C和c++全局名称空间之间的区别。假设你有一个foo。cpp

#include <cstdio>

void foo(int r)
{
  printf("I am C++\n");
}

和foo2.c

#include <stdio.h>

void foo(int r)
{
  printf("I am C\n");
}

现在假设你有一个main.c和main.cpp,它们看起来都是这样的:

extern void foo(int);

int main(void)
{
  foo(1);
  return 0;
}

当编译为c++时,它将使用c++全局命名空间中的符号;在C中,它将使用C:

$ diff main.cpp main.c
$ gcc -o test main.cpp foo.cpp foo2.c
$ ./test 
I am C++
$ gcc -o test main.c foo.cpp foo2.c
$ ./test 
I am C