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

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

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

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


当前回答

这个程序在c++中输出1,在C中输出0:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int d = (int)(abs(0.6) + 0.5);
    printf("%d", d);
    return 0;
}

这是因为在c++中有双abs(double)重载,所以abs(0.6)返回0.6,而在C中它返回0,因为在调用int abs(int)之前,它是隐式的双到整型转换。在C语言中,你必须使用fab与double一起工作。

其他回答

这涉及到C和c++中的左值和右值。

在C编程语言中,加前和加后操作符都返回右值,而不是左值。这意味着它们不能在=赋值操作符的左边。这两个语句都会在C语言中产生编译器错误:

int a = 5;
a++ = 2;  /* error: lvalue required as left operand of assignment */
++a = 2;  /* error: lvalue required as left operand of assignment */

然而,在c++中,前自增操作符返回左值,而后自增操作符返回右值。这意味着带有预增量操作符的表达式可以放在=赋值操作符的左侧!

int a = 5;
a++ = 2;  // error: lvalue required as left operand of assignment
++a = 2;  // No error: a gets assigned to 2!

为什么会这样呢?后增量函数对变量进行递增,并返回该变量在递增发生之前的状态。这实际上就是一个右值。变量a的前一个值作为临时值复制到寄存器中,然后对a进行递增。但是a的前一个值是由表达式返回的,它是一个右值。它不再表示变量的当前内容。

The pre-increment first increments the variable, and then it returns the variable as it became after the increment happened. In this case, we do not need to store the old value of the variable into a temporary register. We just retrieve the new value of the variable after it has been incremented. So the pre-increment returns an lvalue, it returns the variable a itself. We can use assign this lvalue to something else, it is like the following statement. This is an implicit conversion of lvalue into rvalue.

int x = a;
int x = ++a;

由于预增量返回一个左值,我们也可以给它赋值。下面两种说法是相同的。在第二次赋值中,首先对a进行递增,然后用2覆盖它的新值。

int a;
a = 2;
++a = 2;  // Valid in C++.
#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++编程语言(第三版)给出了三个例子:

sizeof('a'),正如@Adam Rosenfield提到的; //注释被用来创建隐藏代码: Int f(Int a, Int b) { 返回a //* blah */ b ; } 结构等隐藏的东西在外部作用域,如在你的例子。

对于C++11标准:

a.逗号操作符在C中执行左值到右值的转换,但在c++中不执行:

   char arr[100];
   int s = sizeof(0, arr);       // The comma operator is used.

在c++中,这个表达式的值是100,在C中是sizeof(char*)。

b.在c++中,枚举器的类型是它的枚举。在C语言中,枚举数的类型是int。

   enum E { a, b, c };
   sizeof(a) == sizeof(int);     // In C
   sizeof(a) == sizeof(E);       // In C++

这意味着sizeof(int)可能不等于sizeof(E)。

c.在c++中,用空参数列表声明的函数不带参数。在C语言中,空参数列表意味着函数参数的数量和类型是未知的。

   int f();           // int f(void) in C++
                      // int f(*unknown*) in C
#include <stdio.h>

int main(void)
{
    printf("%d\n", (int)sizeof('a'));
    return 0;
}

在C语言中,这将打印当前系统中sizeof(int)的值,在目前使用的大多数系统中,这通常是4。

在c++中,这必须打印1。