Answers:
如果您与进行比较C89
,C++
那么以下几点
int n;
int n; // ill-formed: n already defined
int a[1];
int (*ap)[] = &a; // ill-formed: a does not have type int[]
int b(a) int a; { } // ill-formed: grammar error
struct A { struct B { int a; } b; int c; };
struct B b; // ill-formed: b has incomplete type (*not* A::B)
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);
typedef;
在C中是合法的TU,但在C ++中不是。
auto a;
在最新的C ++标准修订版中有效。
a
什么?
auto x;
在最新版本中无效,但例如auto x = 0;
。起初我有些震惊:)
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 ++中编译。
int*
。
void *
,它可以在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
,但名称空间会合并,因此上述C代码段无效。另一方面,C ++专门为允许类型和该类型的类型定义具有相同的名称(显然无效)而允许使用typedef
C不变的技巧。
struct
,union
和enum
)共享相同的命名空间。一个更好的例子是struct foo { ... }; typedef enum { ... } foo;
这也取决于您使用的是哪种C。Stroustrup使C ++尽可能兼容,但不再兼容1989年的ANSI和1990年的ISO标准,而1995年的版本则保持不变。C委员会的方向与1999年标准有所不同,C ++委员会已更改了下一个C ++标准(可能在明年左右发布),以适应某些更改。
Stroustrup在“ C ++编程语言”特别版(这是第3版,其中添加了一些补充材料)的附录B.2中列出了与C90 / C95不兼容的内容:
'a'
int
在C中是C,char
在C ++中是a 。
枚举的大小int
用C表示,不一定用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
变量是隐式的extern
,而在C ++中则不是。C允许多次声明全局数据对象而没有使用extern
,但是在C ++中不是这样。
许多C ++关键字不是C中的关键字,也不是#define
标准C标头中的d。
还有一些C的较旧的功能,它们不再被认为是好的样式。在C语言中,可以在参数列表之后声明带有参数定义的函数。在C中,像这样的声明int foo()
意味着foo()
可以接受任意数量的任何类型的参数,而在C ++中,它等效于int foo(void)
。
这似乎涵盖了Stroustrup的所有内容。
如果使用gcc,则可以使用警告-Wc++-compat
向您发出有关C代码的警告,而C代码在C ++中是可疑的。它目前在gcc本身中使用,并且最近得到了更好的改进(也许可以尝试每晚使用以获得最佳性能)。
(这不能严格回答问题,但人们可能会喜欢)。
我认为最大的不同是这是一个有效的C源文件:
int main()
{
foo();
}
请注意,我还没有声明foo
任何地方。
除了语言差异外,C ++还对其从C继承的库进行了一些更改,例如,某些函数返回const char *
而不是char *
。
s,C,C89,
注意,这是无效的C99源文件。
#include <stdio.h>
int new (int n) {
return n/2;
}
int main(void) {
printf("%d\n", new(10));
return 0;
}
另请参阅C ++常见问题解答条目。
此处的许多答案都涵盖了语法差异,这些语法差异会导致C ++编译器在C89(或C99)源代码上失败。但是,有些细微的语言差异在两种语言中都是合法的,但会产生不同的行为。sizeof (char)
Naveen提到的区别是一个示例,但是编写一个程序,如果将其编译为(ANSI)C程序,则将打印“ C”,而如果将其编译为C ++程序,则将打印“ C ++”,列出了其他一些程序。