User:Ining Chien
注意! 本篇内容来自Wikipedia,中文版节选为User:Ining Chien即用户[1]所翻译,英文版为英文维基百科内容。
C语言和C++的关系十分密切,但是也有许多显著的差异。C++标准起源于早期C标准, 并被设计为与当时的C语言在源代码编写和链接方面很大程度上兼容.[1][2] 因此,两种语言的开发工具(例如IDE和编译器)通常被集成到单个产品中,程序员可以自己选择编写的是C还是C ++,开发工具通常会根据程序员的选择使用不同的编译器和链接器或不同的库。
即便如此,C并不是C++的子集[3], 一般的C语言代码不经修改很难被一些严格符合C++标准的C++编译器成功编译;同样,几乎所有的C++代码都无法被C语言编译器编译。 在这篇文章中,我们主要讨论的是它们在公共部分的差异,比如在C语言中合法的代码到了C++中成为了不合法的代码,或一段代码在C和C++中表现出不同的行为。
C++的创始人Bjarne Stroustrup建议[4] C和C++应该尽可能减小差异,以提高这两种语言的兼容性; 而另一些人则认为C和C++毕竟是两种不同的语言——虽然C++起源于C——因此它们之间的兼容性并不是那么重要。 而ANSI的看法:“我们赞同保持C与C++的最大公共子集原则”,同时“保持它们的差别,使这两种语言继续独立发展”,“......委员会希望C++成为重要的和强有力的语言”。[5][6]
截止到[[C++20]]和C2x,C++不支持部分C语言特性,如变长数组,原生复数支持和restrictTemplate:Link-en。另一方面,与C89相比,C99通过合并C ++功能(例如//注释,允许声明出现在代码中而不只是在函数头)减少了一些其他不兼容性。
在C++中允许但在C++中不允许的语句
C++较C语言有更严格的类型转换和初始化规则[1][7] , 因此一些在C语言里合法的语句在C++里是不合法的。ISO C++附录C.1列出了这些区别。[8]
- 一个常见的区别是在C语言中的指针类型更加弱类型.。具体来说,C语言允许将
void*指针赋值给任何类型的指针而无需强制转换,而C ++则不允许;这个习惯用法经常出现在使用malloc管理内存的C代码中,[9] 或POSIX线程库的上下文传递以及其他涉及回调的框架。例如,下面这个例子在C语言中是可行的,但在C++中不允许:
void *ptr;
/*从void *到int *的隐式转换*/
int *i = ptr;- 或类似的:
int *j = malloc(5 * sizeof *j); /*从void *到int *的隐式转换 */void *ptr;
int *i = (int *)ptr;
int *j = (int *)malloc(5 * sizeof *j);C++中提供了其它方法来实现指针类型转换。C++不推荐继续使用老式类型转换。老式类型转换在形式上来说不是特别清晰,容易被忽略。[12]。
void *ptr;
auto i = reinterpret_cast<int *>(ptr);
auto j = new int[5];- C 允许在安全的前提下隐式添加除const和volatile的关键字,而C++则放弃添加。
- C++为C语言的部分函数添加了一个参数带const的重载,例如
strchr在C语言中的声明为Template:Qcode,而在C++中则有一个重载函数为const char *strchr(const char *)。
- C++在枚举方面也更加严格。在C++中,int不能被隐式转换为枚举类型。因为在C++标准中并没有规定枚举的类型为int(在C语言标准中则规定了),并且大小可能与C++中int的大小不同。从C++11开始,C++允许程序员将自定义的整数类型赋值给枚举类型。
- 在C++中,const变量必须被初始化,但在C语言中不必。也就是说,下面这个例子:
const int var1;
const int var2 = 1;第一行代码在C语言中是允许的(在某些编译器中可能会报告一个“Warning”),但在C++中会报错;第二行代码在C和C++中都是合法的。
- C++不允许Template:Qcode和标签之间出现初始化语句。如下示例所示,该段代码在C语言中是允许的,但在C++中不允许。
void fn(void)
{
goto flack;
int i = 1;
flack:
;
}- 虽然语法上有效,但如果跳过的堆栈帧包含具有非平凡(nontrivial)析构函数的对象(即指针),则longjmp()会在C ++中导致未定义的行为。[13] C++实现可以自由定义此时的行为,以便能够调用析构函数。但是,这样会使Template:Qcode的一些用法失效, 否则就可以通过在单独的调用堆栈之间进行longjmp来实现线程或协程——在全局地址空间中从较低的调用堆栈跳转到较高的调用堆栈时,将析构函数用于较低调用堆栈中的每个对象。这个问题在C语言中不存在。
Template:ProgLangCompare The C and C++ programming languages are closely related but have many significant differences. C++ began as a fork of an early, pre-standardized C, and was designed to be mostly source-and-link compatible with C compilers of the time.[1][14] Due to this, development tools for the two languages (such as IDEs and compilers) are often integrated into a single product, with the programmer able to specify C or C++ as their source language.
However, C is not a subset of C++,[3] and nontrivial C programs will not compile as C++ code without modification. Likewise, C++ introduces many features that are not available in C and in practice almost all code written in C++ is not conforming C code. This article, however, focuses on differences that cause conforming C code to be ill-formed C++ code, or to be conforming/well-formed in both languages but to behave differently in C and C++.
Bjarne Stroustrup, the creator of C++, has suggested[15] that the incompatibilities between C and C++ should be reduced as much as possible in order to maximize inter-operability between the two languages. Others have argued that since C and C++ are two different languages, compatibility between them is useful but not vital; according to this camp, efforts to reduce incompatibility should not hinder attempts to improve each language in isolation. The official rationale for the 1999 C standard (C99) "endorse[d] the principle of maintaining the largest common subset" between C and C++ "while maintaining a distinction between them and allowing them to evolve separately", and stated that the authors were "content to let C++ be the big and ambitious language."[16]
Several additions of C99 are not supported in the current C++ standard or conflicted with C++ features, such as variable-length arrays, native complex number types and the restrict type qualifier. On the other hand, C99 reduced some other incompatibilities compared with C89 by incorporating C++ features such as // comments and mixed declarations and code.[17]
Constructs valid in C but not in C++
C++ enforces stricter typing rules (no implicit violations of the static type system[1]), and initialization requirements (compile-time enforcement that in-scope variables do not have initialization subverted)[18] than C, and so some valid C code is disallowed in C++. A rationale for these is provided in Annex C.1 of the ISO C++ standard.[19]
- One commonly encountered difference is C being more weakly-typed regarding pointers. Specifically, C allows a
void*pointer to be assigned to any pointer type without a cast, while C++ does not; this idiom appears often in C code usingmallocmemory allocation,[9] or in the passing of context pointers to the POSIX pthreads API, and other frameworks involving callbacks. For example, the following is valid in C but not C++:
void *ptr;
/* Implicit conversion from void* to int* */
int *i = ptr;- or similarly:
int *j = malloc(5 * sizeof *j); /* Implicit conversion from void* to int* */- In order to make the code compile as both C and C++, one must use an explicit cast, as follows (with some caveats in both languages[20][21]):
void *ptr;
int *i = (int *)ptr;
int *j = (int *)malloc(5 * sizeof *j);Though C++ favors this:[22]Template:Better source needed
void *ptr;
auto i = reinterpret_cast<int *>(ptr);
auto j = new int[5];- C allows implicitly adding additional non-topmost cv-qualifiers where it is safe, while C++ simply gives up.
- C++ changes some C standard library functions to add additional overloaded functions with
consttype qualifiers, e.g.strchrreturnschar*in C, while C++ acts as if there were two overloaded functionsconst char *strchr(const char *)and achar *strchr(char *).
- C++ is also more strict in conversions to enums: ints cannot be implicitly converted to enums as in C. Also, Enumeration constants (
enumenumerators) are always of typeintin C, whereas they are distinct types in C++ and may have a size different from that ofint. C++11 allows the programmer to use custom integer types for the values of an enum.
- In C++ a
constvariable must be initialized; in C this is not necessary.
- C++ compilers prohibit goto or switch from crossing an initialization, as in the following C99 code:
void fn(void)
{
goto flack;
int i = 1;
flack:
;
}- While syntactically valid, a
longjmp()results in undefined behaviour in C++ if the jumped-over stack frames include objects with nontrivial destructors.[23] The C++ implementation is free to define the behaviour such that destructors would be called. However, this would preclude some uses of longjmp() which would otherwise be valid, such as implementation of threads or coroutines by longjmping between separate call stacks - when jumping from the lower to the upper call stack in global address space, destructors would be called for every object in the lower call stack. No such issue exists in C.
- ↑ 1.0 1.1 1.2 1.3 Stroustrup, Bjarne. An Overview of the C++ Programming Language in The Handbook of Object Technology (Editor: Saba Zamir). CRC Press LLC, Boca Raton. 1999. ISBN 0-8493-3135-8. (PDF): 4. [引用时间: 2009-08-12]. (原始内容 (PDF)存档于2012-08-16). 引用错误:
<ref>标签无效;同一name(名称)“overview”以不同内容定义了多次 - ↑ B.Stroustrup. C and C++: Siblings. The C/C++ Users Journal. July 2002. (PDF). [引用时间: 2019-03-17].
- ↑ 3.0 3.1 Bjarne Stroustrup's FAQ – Is C a subset of C++?. [引用时间: 22 Sep 2019].
- ↑ B. Stroustrup. C and C++: A Case for Compatibility. The C/C++ Users Journal. August 2002. (PDF). [引用时间: 18 August 2013]. (原始内容 (PDF)存档于2012-07-22).
- ↑ Rationale for International Standard—Programming Languages—C Template:Webarchive, revision 5.10 (2003.04).
- ↑ Prata, Stephen. C Primer Plus第5版中文版. 北京: 人民邮电出版社. 2005: 12. ISBN 9787115130228.
- ↑ N4659: Working Draft, Standard for Programming Language C++ (PDF). §Annex C.1. (原始内容 (PDF)存档于2017-12-07). ("It is invalid to jump past a declaration with explicit or implicit initializer (except across entire block not entered). … With this simple compile-time rule, C++ assures that if an initialized variable is in scope, then it has assuredly been initialized.")
- ↑ N4659: Working Draft, Standard for Programming Language C++ (PDF). §Annex C.1. (原始内容 (PDF)存档于7 December 2017).
- ↑ 9.0 9.1 IBM Knowledge Center. ibm.com.
- ↑ FAQ > Casting malloc - Cprogramming.com. (原始内容存档于2007-04-05).
- ↑ 4.4a — Explicit type conversion (casting). 16 April 2015. (原始内容存档于2016-09-25).
- ↑ Lippman, Stanley; Lajoie, Josee; Moo, Barbara. C++ Primer 5th. Addison-Wesley Professional. 2012: 165. ISBN 9780321714114.
- ↑ longjmp - C++ Reference. www.cplusplus.com. (原始内容存档于12 May 2018). 已忽略未知参数
|df=(帮助); 已忽略未知参数|url-status=(帮助) - ↑ B.Stroustrup. C and C++: Siblings. The C/C++ Users Journal. July 2002. (PDF). [引用时间: 17 March 2019].
- ↑ B. Stroustrup. C and C++: A Case for Compatibility. The C/C++ Users Journal. August 2002. (PDF). [引用时间: 18 August 2013]. (原始内容 (PDF)存档于22 July 2012). 已忽略未知参数
|df=(帮助); 已忽略未知参数|url-status=(帮助) - ↑ Rationale for International Standard—Programming Languages—C Template:Webarchive, revision 5.10 (April 2003).
- ↑ C Dialect Options - Using the GNU Compiler Collection (GCC). gnu.org. (原始内容存档于26 March 2014). 已忽略未知参数
|df=(帮助); 已忽略未知参数|url-status=(帮助) - ↑ N4659: Working Draft, Standard for Programming Language C++ (PDF). §Annex C.1. (原始内容 (PDF)存档于7 December 2017). 已忽略未知参数
|df=(帮助); 已忽略未知参数|url-status=(帮助) ("It is invalid to jump past a declaration with explicit or implicit initializer (except across entire block not entered). … With this simple compile-time rule, C++ assures that if an initialized variable is in scope, then it has assuredly been initialized.") - ↑ N4659: Working Draft, Standard for Programming Language C++ (PDF). §Annex C.1. (原始内容 (PDF)存档于7 December 2017). 已忽略未知参数
|df=(帮助); 已忽略未知参数|url-status=(帮助) - ↑ FAQ > Casting malloc - Cprogramming.com. faq.cprogramming.com. (原始内容存档于5 April 2007). 已忽略未知参数
|df=(帮助); 已忽略未知参数|url-status=(帮助) - ↑ 4.4a — Explicit type conversion (casting). 16 April 2015. (原始内容存档于25 September 2016). 已忽略未知参数
|df=(帮助); 已忽略未知参数|url-status=(帮助) - ↑ http://wiki.c2.com/?CstyleCasts
- ↑ longjmp - C++ Reference. www.cplusplus.com. (原始内容存档于12 May 2018). 已忽略未知参数
|df=(帮助); 已忽略未知参数|url-status=(帮助)