C不是C ++的子集?
我读了很多书,C是C ++的一个子集。
有些书说C是C ++的一个子集, 除了小细节 。
在C编译代码时会出现什么情况,而不是C ++?
如果您将C89
与C++
进行比较,那么这里有一些事情
在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 ++中,如果声明一个struct
, union
或enum
,那么它的名字不需要任何限定符即可访问:
struct foo { ... }; foo x; // declare variable
在C中,这是行不通的,因为这样声明的类型存在于它们自己独特的名字空间中。 因此,你必须写:
struct foo { ... }; struct foo x; // declare variable
注意在第二行的struct
存在。 你必须为union
和enum
(使用它们各自的关键字)做同样的事情,或者使用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 ++是不同的语言。