C 在哪里不是 C++ 的子集?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1201593/
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 19:09:57  来源:igfitidea点击:

Where is C not a subset of C++?

c++c

提问by n00ki3

I read in a lot of books that C is a subset of C++.

我在很多书中读到 C 是 C++ 的一个子集。

Some books say that C is a subset of C++, except for the little details.

有些书说C是C++的一个子集,除了一些小细节

What are some cases when code will compile in C, but not C++?

在哪些情况下代码可以用 C 编译,但不能用 C++ 编译?

回答by Johannes Schaub - litb

If you compare C89with C++then here are a couple of things

如果你比较C89C++那么这里有几件事

No tentative definitions in C++

C++ 中没有暂定定义

int n;
int n; // ill-formed: n already defined

int[] and int[N] not compatible (no compatible types in C++)

int[] 和 int[N] 不兼容(C++ 中没有兼容的类型)

int a[1];
int (*ap)[] = &a; // ill-formed: a does not have type int[]

No K&R function definition style

无 K&R 函数定义样式

int b(a) int a; { } // ill-formed: grammar error

Nested struct has class-scope in C++

嵌套结构在 C++ 中具有类范围

struct A { struct B { int a; } b; int c; };
struct B b; // ill-formed: b has incomplete type (*not* A::B)

No default int

无默认整数

auto a; // ill-formed: type-specifier missing


C99 adds a whole lot of other cases

C99 增加了很多其他情况

No special handling of declaration specifiers in array dimensions of parameters

没有对参数数组维度中的声明说明符进行特殊处理

// ill-formed: invalid syntax
void f(int p[static 100]) { }

No variable length arrays

没有变长数组

// ill-formed: n is not a constant expression
int n = 1;
int an[n];

No flexible array member

没有灵活的数组成员

// ill-formed: fam has incomplete type
struct A { int a; int fam[]; }; 

No restrict qualifier for helping aliasing analysis

没有用于帮助混叠分析的限制限定符

// ill-formed: two names for one parameter?
void copy(int *restrict src, int *restrict dst);

回答by Naveen

In C, sizeof('a')is equal to sizeof(int).

在 C 中,sizeof('a')等于sizeof(int)

In C++, sizeof('a')is equal to sizeof(char).

在 C++ 中,sizeof('a')等于sizeof(char).

回答by Graeme Perrow

C++ has new keywords as well. The following is valid C code but won't compile under C++:

C++ 也有新的关键字。以下是有效的 C 代码,但不能在 C++ 下编译:

int class = 1;
int private = 2;
int public = 3;
int virtual = 4;

回答by Mehrdad Afshari

There are plenty of things. Just a simple example (it should be enough to prove C is not a proper subset of C++):

有很多东西。只是一个简单的例子(应该足以证明 C 不是 C++ 的适当子集):

int* test = malloc(100 * sizeof(int));

should compile in C but not in C++.

应该用 C 编译,但不能用 C++ 编译。

回答by Pavel Minaev

In C++, if you declare a struct, union, or enum, its name is immediately accessible without any qualifiers:

在 C++ 中,如果您声明 a struct, union, or enum,则可以立即访问其名称而无需任何限定符:

struct foo { ... };
foo x; // declare variable

In C, this won't work, because types thus declared live in their own distinct namespaces. Thus, you have to write:

在 C 中,这行不通,因为这样声明的类型存在于它们自己不同的命名空间中。因此,你必须写:

struct foo { ... };
struct foo x; // declare variable

Notice the presence of structthere on the second line. You have to do the same for unionand enum(using their respective keywords), or use the typedeftrick:

注意struct第二行那里的存在。你必须对unionenum(使用它们各自的关键字)做同样的事情,或者使用typedef技巧:

typedef struct { ... } foo;
foo x; // declare variable

Consequently, you can have several types of different kinds named the same in C, since you can disambiguate:

因此,您可以在 C 中使用相同名称的几种不同类型,因为您可以消除歧义:

struct foo { ... };
typedef enum { ... } foo;

struct foo x;
foo y;

In C++, however, while you can prefix a structname with keyword structwhenever you reference it, the namespaces are merged, and so the above C snippet isn't valid. On the other hand, C++ specifically makes an exception to allow a type and a typedef for that type to have the same name (obviously with no effect), to allow the use of typedeftrick unchanged from C.

但是,在 C++ 中,虽然您可以在每次引用struct名称时使用关键字作为前缀struct,但名称空间已合并,因此上述 C 代码段无效。另一方面,C++ 专门做了一个例外,允许类型和该类型的 typedef 具有相同的名称(显然没有效果),以​​允许使用typedef与 C 相同的技巧。

回答by David Thornley

This also depends on what variety of C you're using. Stroustrup made C++ as compatible as he could, and no more compatible, with the 1989 ANSI and 1990 ISO standards, and the 1995 version changed nothing. The C committee went in a somewhat different direction with the 1999 standard, and the C++ committee has changed the next C++ standard (probably out next year or so) to conform with some of the changes.

这也取决于您使用的 C 的种类。Stroustrup 使 C++ 与 1989 年的 ANSI 和 1990 年的 ISO 标准尽可能兼容,并且不再兼容,而 1995 年的版本没有任何改变。C 委员会与 1999 年的标准有些不同,C++ 委员会已经更改了下一个 C++ 标准(可能在明年左右发布)以符合一些变化。

Stroustrup lists incompatibilities with C90/C95 in Appendix B.2 of "The C++ Programming Language", Special Edition (which is 3rd edition with some added material):

Stroustrup 在“The C++ Programming Language”特别版(第三版,增加了一些材料)的附录 B.2 中列出了与 C90/C95 的不兼容性:

'a'is an intin C, a charin C++.

'a'int在 C 中是一个,char在 C++ 中是一个。

The sizeof an enum is intin C, not necessarily in C++.

枚举的大小int在 C 中,不一定在 C++ 中。

C++ has //comments to end of line, C doesn't (although it's a common extension).

C++//对行尾有注释,C 没有(尽管它是一个常见的扩展)。

In C++, a struct foo {definition puts foointo the global namespace, while in C it would have to be referred to as struct foo. This allows a structdefinition to shadow a name in an outer scope, and has a few other consequences. Also, C allows larger scope for structdefinitions, and allows them in return type and argument type declarations.

在 C++ 中,struct foo {定义放入foo全局命名空间,而在 C 中,它必须被称为struct foo. 这允许struct定义在外部作用域中隐藏名称,并产生一些其他后果。此外,C 允许更大的struct定义范围,并允许在返回类型和参数类型声明中使用它们。

C++ is fussier about types in general. It won't allow an integer to be assigned to an enum, and void *objects cannot be assigned to other pointer types without a cast. In C, it's possible to provide an overlarge initializer (char name[5] = "David"where C will discard the trailing null character).

C++ 通常对类型更加挑剔。它不允许将整数分配给enum,并且void *对象不能在没有强制转换的情况下分配给其他指针类型。在 C 中,可以提供一个过大的初始值设定项(char name[5] = "David"其中 C 将丢弃尾随的空字符)。

C89 allowed implicit intin many contexts, and C++ doesn't. This means that all functions must be declared in C++, while in C89 it was often possible to get by with assuming intfor everything applicable in the function declaration.

C89 允许int在许多上下文中隐式,而 C++ 不允许。这意味着所有函数都必须在 C++ 中声明,而在 C89 中,通常可以假设int函数声明中适用的所有内容。

In C, it's possible to jump from outside a block to inside using a labeled statement. In C++, this isn't allowed if it skips an initialization.

在 C 中,可以使用带标签的语句从块外部跳转到内部。在 C++ 中,如果跳过初始化,则不允许这样做。

C is more liberal in external linkage. In C, a global constvariable is implicitly extern, and that's not true in C++. C allows a global data object to be declared several times without an extern, but that's not true in C++.

C在外部链接上更自由。在 C 中,全局const变量是隐式的extern,而在 C++ 中则不然。C 允许在没有 的情况下多次声明全局数据对象extern,但在 C++ 中则不然。

Many C++ keywords are not keywords in C, or are #defined in standard C headers.

许多 C++ 关键字在 C 中不是关键字,或者#define在标准 C 头文件中是d。

There are also some older features of C that aren't considered good style any more. In C, you can declare a function with the argument definitions after the list of arguments. In C, a declaration like int foo()means that foo()can take any number of any type of arguments, while in C++ it's equivalent to int foo(void).

也有一些 C 的旧特性不再被认为是好的风格。在 C 中,您可以在参数列表之后使用参数定义声明一个函数。在 C 中,像这样的声明int foo()意味着foo()可以接受任意数量的任何类型的参数,而在 C++ 中它等价于int foo(void).

That seems to cover everything from Stroustrup.

这似乎涵盖了 Stroustrup 的所有内容。

回答by Paul Biggar

If you use gcc, you can use the warning -Wc++-compatto give you warnings about C code which is dubious in C++ in some way. Its currently used in gcc itself, and its gotten a lot better recently (maybe try a nightly version to get the best you can).

如果您使用 gcc,您可以使用警告-Wc++-compat向您发出有关 C 代码的警告,这些代码在 C++ 中以某种方式是可疑的。它目前在 gcc 本身中使用,并且最近变得更好(也许尝试每晚版本以获得最佳效果)。

(This doesn't strictly answer the question, but folk might like it).

(这并不能严格回答问题,但人们可能会喜欢它)。

回答by Daniel Earwicker

The single biggest difference I think is that this is a valid C source file:

我认为最大的区别是这是一个有效的 C 源文件:

int main()
{
    foo();
}

Note that I haven't declared fooanywhere.

请注意,我没有foo在任何地方声明。

Aside from language differences, C++ also makes some changes to the library that it inherited from C, e.g. some functions return const char *instead of char *.

除了语言差异之外,C++ 还对其从 C 继承的库进行了一些更改,例如某些函数返回const char *而不是char *.

回答by Sinan ünür

#include <stdio.h>

int new (int n) {
    return n/2;
}

int main(void) {
    printf("%d\n", new(10));
    return 0;
}

See also the C++ FAQ entry.

另请参阅C++ FAQ 条目

回答by jamesdlin

A number of the answers here cover syntax differences that would cause C++ compilers to fail on C89 (or C99) source code. However, there are some subtle language differences that are legal in both languages but that would produce different behavior. The sizeof (char)difference that Naveen mentioned is one example, but Write a program that will print "C" if compiled as an (ANSI) C program, and "C++" if compiled as a C++ programlists some others.

这里的许多答案涵盖了会导致 C++ 编译器在 C89(或 C99)源代码上失败的语法差异。但是,存在一些细微的语言差异,在两种语言中都是合法的,但会产生不同的行为。sizeof (char)Naveen 提到的区别是一个例子,但编写一个程序,如果编译为(ANSI)C 程序,将打印“C”,如果编译为 C++ 程序,则“C++”列出了其他一些程序