• Moegirl.ICU:萌娘百科流亡社群 581077156(QQ),欢迎对萌娘百科运营感到失望的编辑者加入
  • Moegirl.ICU:账号认领正在试运行,有意者请参照账号认领流程

使用者: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 *的隐式转换 */
為了使代碼在C和C++中同時可用, 必須使用強制類型轉換, 如下所示 (然而這樣在兩種語言中都會報警告[10][11]):
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 using malloc memory 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 const type qualifiers, e.g. strchr returns char* in C, while C++ acts as if there were two overloaded functions const char *strchr(const char *) and a char *strchr(char *).
  • C++ is also more strict in conversions to enums: ints cannot be implicitly converted to enums as in C. Also, Enumeration constants (enum enumerators) are always of type int in C, whereas they are distinct types in C++ and may have a size different from that of int. C++11 allows the programmer to use custom integer types for the values of an enum.
  • In C++ a const variable 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. 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」使用不同內容定義了多次
  2. B.Stroustrup. C and C++: Siblings. The C/C++ Users Journal. July 2002. (PDF). [引用時間: 2019-03-17]. 
  3. 3.0 3.1 Bjarne Stroustrup's FAQ – Is C a subset of C++?. [引用時間: 22 Sep 2019]. 
  4. B. Stroustrup. C and C++: A Case for Compatibility. The C/C++ Users Journal. August 2002. (PDF). [引用時間: 18 August 2013]. (原始內容 (PDF)存檔於2012-07-22). 
  5. Rationale for International Standard—Programming Languages—C Template:Webarchive, revision 5.10 (2003.04).
  6. Prata, Stephen. C Primer Plus第5版中文版. 北京: 人民郵電出版社. 2005: 12. ISBN 9787115130228. 
  7. 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.")
  8. N4659: Working Draft, Standard for Programming Language C++ (PDF). §Annex C.1. (原始內容 (PDF)存檔於7 December 2017). 
  9. 9.0 9.1 IBM Knowledge Center. ibm.com. 
  10. FAQ > Casting malloc - Cprogramming.com. (原始內容存檔於2007-04-05). 
  11. 4.4a — Explicit type conversion (casting). 16 April 2015. (原始內容存檔於2016-09-25). 
  12. Lippman, Stanley; Lajoie, Josee; Moo, Barbara. C++ Primer 5th. Addison-Wesley Professional. 2012: 165. ISBN 9780321714114. 
  13. longjmp - C++ Reference. www.cplusplus.com. (原始內容存檔於12 May 2018).  已忽略未知參數|df= (幫助); 已忽略未知參數|url-status= (幫助)
  14. B.Stroustrup. C and C++: Siblings. The C/C++ Users Journal. July 2002. (PDF). [引用時間: 17 March 2019]. 
  15. 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= (幫助)
  16. Rationale for International Standard—Programming Languages—C Template:Webarchive, revision 5.10 (April 2003).
  17. C Dialect Options - Using the GNU Compiler Collection (GCC). gnu.org. (原始內容存檔於26 March 2014).  已忽略未知參數|df= (幫助); 已忽略未知參數|url-status= (幫助)
  18. 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.")
  19. N4659: Working Draft, Standard for Programming Language C++ (PDF). §Annex C.1. (原始內容 (PDF)存檔於7 December 2017).  已忽略未知參數|df= (幫助); 已忽略未知參數|url-status= (幫助)
  20. FAQ > Casting malloc - Cprogramming.com. faq.cprogramming.com. (原始內容存檔於5 April 2007).  已忽略未知參數|df= (幫助); 已忽略未知參數|url-status= (幫助)
  21. 4.4a — Explicit type conversion (casting). 16 April 2015. (原始內容存檔於25 September 2016).  已忽略未知參數|df= (幫助); 已忽略未知參數|url-status= (幫助)
  22. http://wiki.c2.com/?CstyleCasts
  23. longjmp - C++ Reference. www.cplusplus.com. (原始內容存檔於12 May 2018).  已忽略未知參數|df= (幫助); 已忽略未知參數|url-status= (幫助)