Where is C not a subset of C++?
我在很多书中读到C是C++的一个子集。
有些书说C是C++的一个子集,除了一些小细节。
什么时候代码会在C中编译,而不是C++?
如果你把
1 2 | int n; int n; // ill-formed: n already defined |
。INT[]和INT[N]不兼容(C++中没有兼容类型)
1 2 | int a[1]; int (*ap)[] = &a; // ill-formed: a does not have type int[] |
无K&R函数定义样式
1 | int b(a) int a; { } // ill-formed: grammar error |
。嵌套结构在C++中具有类作用域
1 2 | struct A { struct B { int a; } b; int c; }; struct B b; // ill-formed: b has incomplete type (*not* A::B) |
号无默认int
1 | auto a; // ill-formed: type-specifier missing |
号
C99增加了很多其他案例
参数数组维数中的声明说明符没有特殊处理1 2 | // ill-formed: invalid syntax void f(int p[static 100]) { } |
号没有可变长度数组
1 2 3 | // ill-formed: n is not a constant expression int n = 1; int an[n]; |
号没有灵活的数组成员
1 2 | // ill-formed: fam has incomplete type struct A { int a; int fam[]; }; |
号没有用于帮助别名分析的限制限定符
1 2 | // ill-formed: two names for one parameter? void copy(int *restrict src, int *restrict dst); |
号
在c中,
在C++中,EDCOX1〔0〕等于EDCOX1〔3〕。
C++也有新的关键词。以下是有效的C代码,但不能在C++下编译:
1 2 3 4 | int class = 1; int private = 2; int public = 3; int virtual = 4; |
有很多东西。只是一个简单的例子(它应该足以证明C不是C++的正确子集):
1 | int* test = malloc(100 * sizeof(int)); |
应该在C中编译,而不是在C++中编译。
在C++中,如果你声明一个EDCOX1,7,EDCOX1,8,或EDOCX1,9,它的名字可以立即访问,没有任何限定符:
1 2 | struct foo { ... }; foo x; // declare variable |
在C中,这不起作用,因为这样声明的类型活在它们自己独特的名称空间中。因此,你必须写:
1 2 | struct foo { ... }; struct foo x; // declare variable |
。
注意第二行有
1 2 | typedef struct { ... } foo; foo x; // declare variable |
。
因此,您可以在C中有几种不同类型的名称相同,因为您可以消除歧义:
1 2 3 4 5 | struct foo { ... }; typedef enum { ... } foo; struct foo x; foo y; |
然而,在C++中,虽然您可以用EDOCX1 7的名称对EDCOX1的7个名称进行前缀,但是每当引用它时,名称空间就被合并,因此上面的C代码段无效。另一方面,C++专门允许一个类型和一个类型的TyPulf具有相同的名称(显然没有影响),以允许使用EcOCX1×13的技巧。
这还取决于你使用的是哪种C。Stroustrup使C++与他兼容,并且不兼容,与1989 ANSI和1990 ISO标准兼容,而1995版本没有改变。C委员会在1999个标准上有一个不同的方向,C++委员会改变了下一个C++标准(可能是明年左右),以适应一些变化。
StruouUp列出了与C90/C95在"C++编程语言"附录B2中的不兼容性,特别版(第三版加上一些附加材料):
EDCOX1〔0〕是C中的EDCOX1×1,在C++中是EDCOX1×2的一个EDCOX1。
EnUM的大小是C中的EDOCX1×1,不一定是C++。
C++有EDOCX1的4个注释到结束行,C没有(尽管它是一个常见的扩展)。
在C++中,一个EDCOX1×5的定义将EDCOX1(6)插入到全局命名空间中,而在C中,它必须被称为EDCOX1×7。这允许
一般来说,C++是比较常用的类型。它不允许将整数赋给
C89允许在许多上下文中隐含EDOCX1 1,而C++没有。这意味着所有函数都必须在C++中声明,而在C89中,通常可以假设EDCOX1为1,适用于函数声明中适用的任何东西。
在C语言中,可以使用带标签的语句从块外部跳到块内部。在C++中,如果跳过初始化,则不允许这样做。
C在外部联系上更为自由。在C中,一个全局EDCOX1×15变量是隐式EDOCX1,16表示,这在C++中是不正确的。C允许一个全局数据对象被声明多次,而不需要EDCOX1,16,但是在C++中这是不正确的。
许多C++关键字不是C中的关键字,或者是标准C标题中的EDCOX1×18×D。
还有一些C的老特性不再被认为是好的样式。在C语言中,可以在参数列表之后声明一个带有参数定义的函数。在C中,像EDCOX1(19)那样的声明意味着EDCOX1(20)可以取任意数量的任何类型的参数,而在C++中,它相当于EDCOX1×21。
这似乎涵盖了stroustrup的所有内容。
如果你使用GCC,你可以使用警告EDOCX1 22来警告C代码,这在某些方面是可疑的。它目前在GCC本身中使用,并且最近变得更好了(也许可以尝试一个夜间版本以获得最好的效果)。
(这并不能严格回答这个问题,但人们可能会喜欢它)。
我认为最大的区别是这是一个有效的C源文件:
1 2 3 4 | int main() { foo(); } |
。
请注意,我没有在任何地方声明过
除了语言差异之外,C++还对从C继承的库进行了一些更改,例如一些函数返回EDCOX1×5,而不是EDCOX1(6)。
1 2 3 4 5 6 7 8 9 10 11 | #include <stdio.h> int new (int n) { return n/2; } int main(void) { printf("%d ", new(10)); return 0; } |
号
请参阅C++ FAQ条目。
这里的一些答案涵盖了语法差异,这会导致C++编译器在C89(或C99)源代码上失败。然而,在两种语言中都有一些微妙的语言差异是合法的,但会产生不同的行为。Naveen提到的EDCOX1×23差异是一个例子,但是如果编译成一个(ANSI)C程序,则编写一个程序,它将打印"C",而"C++"如果被编译为C++程序,则列出一些其他程序。
不能只按语法比较语言。如果你这样做,也许你可以看到C作为C++的一个子集。在我看来,C++是OO(而C不是)这一事实足以说明C语言和C++语言是不同的语言。
C编译器通常允许一个小的角切割,C++没有。C++比C.严格得多,一般来说,这些差异中的一些是编译器依赖的。G++允许一些英特尔C++编译器不需要的东西。即使写得相当好的C代码也不能用现代C++编译器编译。