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

Where is C not a subset of C++?

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

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

什么时候代码会在C中编译,而不是C++?


如果你把C89C++作比较,那么这里有两件事

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中,sizeof('a')等于sizeof(int)

在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

注意第二行有struct的存在。您必须对unionenum执行相同的操作(使用它们各自的关键字),或者使用typedef技巧:

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。这允许struct定义在外部作用域中隐藏名称,并有一些其他后果。此外,C允许更大的范围用于struct定义,并允许在返回类型和参数类型声明中使用它们。

一般来说,C++是比较常用的类型。它不允许将整数赋给enum,如果没有强制转换,则无法将void *对象赋给其他指针类型。在C中,可以提供一个过大的初始值设定项(char name[5] ="David",其中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();
}

请注意,我没有在任何地方声明过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++编译器编译。