C不是C ++的子集?

我读了很多书,C是C ++的一个子集。

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

在C编译代码时会出现什么情况,而不是C ++?

如果您将C89C++进行比较,那么这里有一些事情

在C ++中没有尝试性的定义

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

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

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

没有K&R功能定义样式

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

嵌套结构在C ++中有类作用域

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

没有默认的int

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

C99增加了很多其他的情况

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

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

没有可变长度的数组

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

没有灵活的阵列成员

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

没有限制条件来帮助混叠分析

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

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

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

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

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

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

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

应该用C编译而不用C ++编译。

在C ++中,如果声明一个structunionenum ,那么它的名字不需要任何限定符即可访问:

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

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

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

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

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

因此,你可以在C中有几种不同类型的命名,因为你可以消除歧义:

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

然而,在C ++中,尽管每当引用struct名称时都可以使用关键字struct作为struct名称,但命名空间是合并的,所以上面的C代码片段是无效的。 另一方面,C ++专门制定了一个例外,允许该类型的类型和类型定义具有相同的名称(显然没有效果),以​​允许使用从C中未改变的typedef技巧。

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

Stroustrup在“C ++编程语言”特别版(第3版增加了一些内容)的附录B.2中列出了与C90 / C95不兼容的地方:

'a'是C中的一个char ,C ++中的一个char

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

C ++具有//注释行结束,C不(尽管这是一个常见的扩展)。

在C ++中, struct foo {定义将foo放入全局名称空间,而在C中则必须将其称为struct foo 。 这允许一个struct定义在一个外部范围中映射一个名字,并且还有一些其他的后果。 此外,C允许struct定义的范围更大,并允许它们返回类型和参数类型声明。

一般来说C ++对于类型来说很麻烦。 它不会允许将整数分配给enum ,并且void *对象不能在没有强制转换的情况下分配给其他指针类型。 在C中,可以提供一个过大的初始化程序( char name[5] = "David" ,其中C将放弃结尾的空字符)。

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

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

C在外部联系上更为自由。 在C中,一个全局的const变量是隐式的,这在C ++中是不正确的。 C允许一个全局数据对象多次声明而不需要extern ,但是在C ++中不是这样。

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

还有一些C的旧功能,不再被认为是好的风格。 在C中,你可以在参数列表之后声明一个带参数定义的函数。 在C中,像int foo()这样的声明意味着foo()可以接受任何类型的参数,而在C ++中它相当于int foo(void)

这似乎涵盖了从Stroustrup的一切。

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

 int main() { foo(); } 

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

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

 #include <stdio.h> int new (int n) { return n/2; } int main(void) { printf("%d\n", new(10)); return 0; } 

另请参阅C ++ FAQ条目 。

如果你使用gcc,你可以使用警告-Wc++-compat来给你一些关于C代码的警告,这在C ++中是可疑的。 它目前在gcc中使用,最近它变得更好了(也许试试每晚版本以获得最好的结果)。

(这个问题并不严格回答,但民间人士可能会喜欢)。

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

C编译器通常允许C ++没有的一点切角。 C ++比C更严格。通常,这些差异中有一些是依赖于编译器的。 例如,g ++允许一些Intel C ++编译器不支持的东西。 即使编写得很好的C代码也不会用现代C ++编译器编译。

只能通过语法来比较语言。 如果你这样做,也许你可以看到C作为C ++的一个子集。 在我看来,C ++是OO(而C不是)足以说C和C ++是不同的语言。