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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12887700/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 16:43:39  来源:igfitidea点击:

Can code that is valid in both C and C++ produce different behavior when compiled in each language?

c++c

提问by user541686

C and C++ have many differences, and not all valid C code is valid C++ code.
(By "valid" I mean standard code with defined behavior, i.e. not implementation-specific/undefined/etc.)

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

Is there any scenario in which a piece of code valid in both C and C++ would produce differentbehavior when compiled with a standard compiler in each language?

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

To make it a reasonable/useful comparison (I'm trying to learn something practically useful, not to try to find obvious loopholes in the question), let's assume:

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

  • Nothing preprocessor-related (which means no hacks with #ifdef __cplusplus, pragmas, etc.)
  • Anything implementation-defined is the same in both languages (e.g. numeric limits, etc.)
  • We're comparing reasonably recent versions of each standard (e.g. say, C++98 and C90 or later)
    If the versions matter, then please mention which versions of each produce different behavior.
  • 没有与预处理器相关的内容(这意味着没有 hack #ifdef __cplusplus、pragma 等)
  • 任何实现定义在两种语言中都是相同的(例如数字限制等)
  • 我们正在比较每个标准的最新版本(例如,C++98 和 C90 或更高版本)
    如果版本很重要,那么请说明每个标准的哪些版本会产生不同的行为。

采纳答案by Alexey Frunze

The following, valid in C and C++, is going to (most likely) result in different values in iin C and C++:

以下在 C 和 C++ 中有效,将(最有可能)i在 C 和 C++ 中产生不同的值:

int i = sizeof('a');

See Size of character ('a') in C/C++for an explanation of the difference.

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

Another one from this article:

这篇文章中的另一个:

#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;
}

回答by Seth Carnegie

Here is an example that takes advantage of the difference between function calls and object declarations in C and C++, as well as the fact that C90 allows the calling of undeclared functions:

下面是一个示例,它利用了 C 和 C++ 中函数调用和对象声明之间的差异,以及 C90 允许调用未声明函数的事实:

#include <stdio.h>

struct f { int x; };

int main() {
    f();
}

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

In C++ this will print nothing because a temporary fis created and destroyed, but in C90 it will print hellobecause functions can be called without having been declared.

在 C++ 中,这不会打印任何内容,因为f创建和销毁了临时文件,但在 C90 中,它会打印,hello因为可以在未声明的情况下调用函数。

In case you were wondering about the name fbeing used twice, the C and C++ standards explicitly allows this, and to make an object you have to say struct fto disambiguate if you want the structure, or leave off structif you want the function.

如果您想知道名称f被使用了两次,C 和 C++ 标准明确允许这样做,并且要创建一个对象,您必须说struct f如果需要结构就消除歧义,或者struct如果需要函数就放弃。

回答by Jerry Coffin

For C++ vs. C90, there's at least one way to get different behavior that's not implementation defined. C90 doesn't have single-line comments. With a little care, we can use that to create an expression with entirely different results in C90 and in C++.

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

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

In C++, everything from the //to the end of the line is a comment, so this works out as:

在 C++ 中,从//行尾到行尾的所有内容都是注释,因此其结果如下:

int a = 10 + 3;

Since C90 doesn't have single-line comments, only the /* comment */is a comment. The first /and the 2are both parts of the initialization, so it comes out to:

由于 C90 没有单行注释,因此只有/* comment */is 注释。first/和 the2都是初始化的一部分,所以结果是:

int a = 10 / 2 + 3;

So, a correct C++ compiler will give 13, but a strictly correct C90 compiler 8. Of course, I just picked arbitrary numbers here -- you can use other numbers as you see fit.

因此,正确的 C++ 编译器将给出 13,而严格正确的 C90 编译器将给出 8。当然,我只是在此处选择了任意数字——您可以使用您认为合适的其他数字。

回答by detunized

C90 vs. C++11 (intvs. double):

C90 与 C++11(int对比double):

#include <stdio.h>

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

In C automeans local variable. In C90 it's ok to omit variable or function type. It defaults to int. In C++11 automeans something completely different, it tells the compiler to infer the type of the variable from the value used to initialize it.

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

回答by godlygeek

Another example that I haven't seen mentioned yet, this one highlighting a preprocessor difference:

另一个我还没有看到提到的例子,这个突出了预处理器的区别:

#include <stdio.h>
int main()
{
#if true
    printf("true!\n");
#else
    printf("false!\n");
#endif
    return 0;
}

This prints "false" in C and "true" in C++ - In C, any undefined macro evaluates to 0. In C++, there's 1 exception: "true" evaluates to 1.

这会在 C 中打印“false”,在 C++ 中打印“true” - 在 C 中,任何未定义的宏的计算结果为 0。在 C++ 中,有 1 个例外:“true”的计算结果为 1。

回答by Kirill Kobelev

Per C++11 standard:

根据 C++11 标准:

a.The comma operator performs lvalue-to-rvalue conversion in C but not C++:

一种。逗号运算符在 C 但不是 C++ 中执行左值到右值的转换:

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

In C++ the value of this expression will be 100 and in C this will be sizeof(char*).

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

b.In C++ the type of enumerator is its enum. In C the type of enumerator is int.

在 C++ 中,枚举器的类型是它的枚举。在 C 中,枚举器的类型是 int。

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

This means that sizeof(int)may not be equal to sizeof(E).

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

c.In C++ a function declared with empty params list takes no arguments. In C empty params list mean that the number and type of function params is unknown.

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

   int f();           // int f(void) in C++
                      // int f(*unknown*) in C

回答by Pavel Chikulaev

This program prints 1in C++ and 0in C:

这个程序1用 C++ 和0C打印:

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

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

This happens because there is double abs(double)overload in C++, so abs(0.6)returns 0.6while in C it returns 0because of implicit double-to-int conversion before invoking int abs(int). In C, you have to use fabsto work with double.

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

回答by Adam Rosenfield

#include <stdio.h>

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

In C, this prints whatever the value of sizeof(int)is on the current system, which is typically 4in most systems commonly in use today.

在 C 中,这会打印sizeof(int)当前系统上的任何值,这通常4在当今常用的大多数系统中。

In C++, this must print 1.

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

回答by Alex B

Another sizeoftrap: boolean expressions.

另一个sizeof陷阱:布尔表达式。

#include <stdio.h>
int main() {
    printf("%d\n", (int)sizeof !0);
}

It equals to sizeof(int)in C, because the expression is of type int, but is typically 1 in C++ (though it's not required to be). In practice they are almost always different.

sizeof(int)在 C 中等于,因为表达式的类型为int,但在 C++ 中通常为 1(尽管它不是必需的)。在实践中,它们几乎总是不同的。

回答by derobert

The C++ Programming Language (3rd Edition)gives three examples:

C++编程语言(第3版)给出了三个例子:

  1. sizeof('a'), as @Adam Rosenfield mentioned;

  2. //comments being used to create hidden code:

    int f(int a, int b)
    {
        return a //* blah */ b
            ;
    }
    
  3. Structures etc. hiding stuff in out scopes, as in your example.

  1. sizeof('a'),正如@Adam Rosenfield 提到的;

  2. //用于创建隐藏代码的注释:

    int f(int a, int b)
    {
        return a //* blah */ b
            ;
    }
    
  3. 结构等将东西隐藏在范围之外,如您的示例所示。