C与C++的兼容性
C语言和C++的关系相当密切,但是也存在许多显著的差异。C++标准起源于早期C标准, 并被设计为与当时的C语言在源代码编写和链接方面很大程度上兼容。 因此,两种语言的开发工具(例如IDE和编译器)通常被集成到单个产品中,程序员可以自己选择编写的是C还是C++,开发工具通常会根据程序员的选择使用不同的编译器和链接器或不同的库。
但是,C并不是C++的子集, 一般的 C 代码不经修改很难被一些严格符合C++标准的C++编译器成功编译;同样,C++ 引入了许多 C 中没有的特性,所以,几乎所有用 C++ 编写的代码都无法被 C 编译器成功编译。在这篇文章中,我们主要讨论的是它们在公共部分的差异,比如在C语言中合法的代码到了C++中成为了不合法的代码,或一段代码在C和C++中表现出不同的行为。
C++的创始人Bjarne Stroustrup建议 C和C++应该尽可能减小差异,以最大限度地提高这两种语言的兼容性;而另一些人则认为C和C++毕竟是两种不同的语言——虽然C++起源于C——因此它们之间的兼容性并不是那么重要。 而ANSI是这样看的:「我们赞同保持C与C++的最大公共子集原则」,同时「保持它们的差别,使这两种语言继续独立发展」,「……委员会希望C++成为重要的和强有力的语言。」
截止到C++20和C2x,C++ 还是不支持部分C语言特性,如变长数组,原生复数支持和codice_1。另一方面,与C89相比,C99通过合并C++功能(例如codice_2注释,允许声明出现在代码中而不只是在函数头)减少了一些其他不兼容性。
在C中允许而在C++中不允许存在的代码语句.
C++较C语言有更严格的类型转换和初始化规则 , 因此一些在C语言里合法的语句在C++里是不合法的。ISO C++附录C.1中列出了这些区别。
/*从void *到int *的隐式转换*/
int *i = ptr;
或类似的:
int *j = malloc(5 * sizeof *j); /*从void *到int *的隐式转换 */
为了使代码在C和C++中同时可用, 必须使用强制类型转换, 如下所示(然而这样在两种语言中都会报警告):
void *ptr;
int *i = (int *)ptr;
int *j = (int *)malloc(5 * sizeof *j);
C++中提供了其它方法来实现指针类型转换。C++不推荐继续使用老式类型转换。老式类型转换在形式上来说不是特别清晰,容易被忽略。。
void *ptr;
auto i = reinterpret_cast(ptr);
auto j = new int[5];
const int var1;
const int var2 = 1;
第一行代码在C语言中是允许的(在某些编译器中可能会报告“Warning”),但在C++中会报错;第二行代码在C和C++中都是合法的。
void fn(void)
goto flack;
int i = 1;
flack:
enum BOOL {FALSE, TRUE};
typedef int BOOL;//在C语言中允许,在C++中不允许
struct foo{
int bar;
/*
在C++中,以上形式被隐式转换为:
typedef struct foo{
int bar;
} foo;
struct foo foobar;//在C与C++中均可
foo foobar2; //在C语言中不允许,在C++中允许
int add(a,b)
int a;
int b;
return a+b;
struct foo{
struct bar{
int x;
int y;
然而,在使用时,C和C++采用不同的方法,假设此时已有struct foo类型变量a, 且x = 1,y = 2;如要将x赋值给变量b,c:
//以下是C语言方法,在C++中不允许:
int b = a.x;
//以下是C++特有方法,在C中不允许:
int c = a::x
void foo(size_t x, int a[*]); // 使用VLA的函数
void foo(size_t x, int a[x])
printf("%zu\n", sizeof a); // 等同于sizeof(int*)
char s[x*2];
printf("%zu\n", sizeof s); // 将显示x*2
struct X
int n, m;
char bytes[];
int foo(int a[const]); // 相当于int foo(int *const a);
int bar(char s[static 5]); // 表示s的长度至少为5
struct X a = (struct X){4, 6}; // 在C++ 中等于 X{4, 6}.
struct X a = {.n = 4, .m = 6};
char s[20] = {[0] = 'a', [8]='g'};
struct template
int new;
struct template* class;
以上代码在C语言中是允许的,但是在C++中不允许。
在C和C++中行为不同的语句.
有一些语句在C和C++中都有效,但是在两种语言中会产生不同的结果。
/* Copyright (C) 1998-2020 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
. */
* ISO C Standard: 7.16 Boolean type and values
需要注意的是,codice_54在C语言中被储存为int类型。
extern int T;
int size(void)
struct T { int i; int j; };
return sizeof(T);
/* C: return sizeof(int)
* C++: return sizeof(struct T)
这是因为在C语言中,struct(结构体)类型前需要添加“codice_17”,而在这个例子中,因为codice_60前没有codice_17,所以它所代表的是在外部定义的int变量;而在C++中,因为可以省略codice_17,因此造成了歧义。然而,在C++中如果使用codice_63这种形式,编译器会更倾向于认为T是一个表达式,因此编译会出错;而在C语言中则不会。
生成维基百科快照图片,大概需要3-30秒!