C와 C++의 호환성

Compatibility of C and C++

C와 C++ 프로그래밍 언어는 밀접하게 관련되어 있지만 많은 차이가 있습니다.C++는 초기 표준화 C의 분기점에서 시작되었으며, 대부분 당시의 [1][2]C 컴파일러와 소스 및 링크 호환되도록 설계되었습니다.그 때문에, 2개의 언어(IDE컴파일러등)의 개발 툴이 1개의 제품에 짜넣어지는 경우가 많아, 프로그래머는 C 또는 C++ 를 소스 언어로 지정할 수 있습니다.

단, C는 C++[3]의 서브셋이 아니며, 중요하지 않은 C 프로그램은 수정 없이 C++ 코드로 컴파일되지 않습니다.마찬가지로 C++는 C에서는 사용할 수 없는 많은 기능을 도입하고 있습니다.실제로 C++로 기술되어 있는 거의 모든 코드는 C코드에 준거하고 있습니다.다만, 이 문서에서는, C코드의 형식이 올바르지 않은 C++코드, 또는 양쪽 언어에서의 적합/정형성을 일으키는 차이에 초점을 맞추고 있습니다만, C코드와 C++코드의 동작은 다릅니다.

C++를 만든 Bjarne Stroustrup은 두 언어 간의 상호 운용성을 극대화하기 위해 C와 C++ 간의 호환성을 최대한 줄여야 한다고 제안했습니다[4].다른 사람들은 C와 C++가 두 개의 다른 언어이기 때문에 이들 사이의 호환성은 유용하지만 필수적이지 않다고 주장해왔다. 이 캠프에 따르면 호환성을 줄이려는 노력은 각 언어를 독립적으로 개선하려는 시도를 방해해서는 안 된다.1999년 C 표준(C99)의 공식적 근거는 "C와 C++ 사이의 가장 큰 공통 서브셋을 유지하는 원칙을 고수하고 C++가 개별적으로 진화하도록 허용한다"며 저자들이 "C++가 크고 야심찬 언어가 되도록 하는 내용"이라고 명시했다."[5]

현재의 C++ 표준에서는 C99의 몇 가지 추가가 지원되지 않거나 가변장 어레이, 네이티브 복합번호 타입 및 C++ 기능과 경합합니다.restrict 수식자를 입력합니다.한편, C99는 다음과 같은 C++ 기능을 통합함으로써 C89와 비교하여 일부 다른 비호환성을 줄였습니다.//코멘트 및 선언과 코드가 [6]혼재되어 있습니다.

C에서는 유효하지만 C++에서는 유효하지 않은 구성

C++는 C보다 더 엄격한 타이핑 규칙(스태틱타입[1] 시스템의 암묵적인 위반 없음)과 초기화 요건(범위 내 변수에 초기화가 하위화되지 [7]않는 컴파일 시간 적용)을 적용하기 때문에 C++에서는 유효한 C 코드 중 일부가 무효입니다.이에 대한 근거는 ISO C++ [8]표준의 부록 C.1에 제시되어 있다.

  • 일반적으로 볼 수 있는 한 가지 차이점은 C가 포인터에 대해 더 약하게 입력된다는 것입니다.구체적으로는 C에 의해void*C++는 캐스트 없이 임의의 포인터 타입에 할당되는 포인터.이 관용구는 C코드에 자주 나타난다.malloc메모리 [9]할당 또는 POSIX pthreads API 및 콜백을 포함하는 기타 프레임워크에 대한 컨텍스트 포인터 전달 중.예를 들어 C에서는 유효하지만 C++에서는 유효하지 않습니다.
    무효 *ptr; /* 보이드에서 int*로의 암묵적인 변환 */ 인트 *i = ptr; 

    또는 이와 유사합니다.

    인트 *j = 마로크(5 * 크기 *j);     /* 보이드에서 int*로의 암묵적인 변환 */ 

    코드를 C와 C++로 컴파일하려면 다음과 같이 명시적 캐스트를 사용해야 합니다(양쪽[10][11] 언어로 몇 가지 주의사항이 있습니다).

    무효 *ptr; 인트 *i = (인트 *)ptr; 인트 *j = (인트 *)마로크(5 * 크기 *j); 
  • C++는 포인터 할당에 대해 보다 복잡한 규칙을 가지고 있으며 수식자를 추가합니다.int **로.const int *const *하지만 안전하지 않은 할당은 아니다.const int **한편, C는 어느쪽도 허가하지 않습니다(단, 컴파일러는 통상은 경고만 송신합니다).
  • C++는 일부 C 표준 라이브러리 함수를 변경하여 오버로드된 기능을 추가합니다.const 수식자를 입력합니다(예:strchr돌아온다char*C++는 2개의 오버로드된 함수가 있는 것처럼 동작합니다.const char *strchr(const char *)및 achar *strchr(char *).
  • 또한 C++는 enum으로 변환하는 경우 더욱 엄격합니다.C와 같이 int를 enum으로 암묵적으로 변환할 수 없습니다.또한 열거 상수(enum열거자)는 항상 유형입니다.intC에서, 반면 C++에서는 구별되는 유형이며, C++에서는 다른 크기를 가질 수 있다.int.
  • C++ a의 경우const변수를 초기화해야 합니다.C 에서는, 이것은 필요 없습니다.
  • C++ 컴파일러는 다음 C99 코드와 같이 goto 또는 스위치가 초기화를 통과하는 것을 금지합니다.
    무효 fn(무효) {     에 가다 플랙;     인트 i = 1; 플랙:     ; } 
  • 구문적으로는 유효하지만, 에 의해 C++에서 정의되지 않은 동작이 발생합니다.이는 점프오버스택 프레임에 중요한 디스트럭터가 [12]없는 오브젝트가 포함되어 있는 경우입니다.C++ 실장은 디스트럭터가 호출되도록 동작을 자유롭게 정의할 수 있습니다.다만, 이것은, 다음의 몇개의 사용을 배제합니다.longjmp()그렇지 않으면 스레드 또는 코루틴의 실장 등, 다른 콜스택간의 전환이 유효하게 됩니다.longjmp(): 글로벌 주소 공간의 하위 콜스택에서 상위 콜스택으로 점프할 경우 하위 콜스택 내의 모든 오브젝트에 대해 디스트럭터가 호출됩니다.C에는 이러한 문제가 없습니다.
  • C에서는 단일 변환 단위로 단일 글로벌 변수를 여러 잠정적으로 정의할 수 있습니다.이것은 C++에서의 ODR 위반으로 무효입니다.
    인트 N; 인트 N = 10; 
  • C에서 기존과 동일한 이름의 새 유형 선언struct,union또는enum유효하지만 C++에서는 무효입니다.C 에서는,struct,union,그리고.enumC++에서는 이러한 유형의 모든 선언이 암묵적으로 typedef를 전달합니다.
    열거하다 부루 {거짓의, 진실의}; 유형화된 인트 부루; 
  • ("K&,Non-prototypeR"-style)함수 선언 C++에서, 그들이 사용되지 않게 되는 1990년에 C의 원래 표준화 이후게 간주된다고 그들은 여전히 C,[13]에 유효하다.(이 용어가 잘못된 경우"obsolescent"ISOC표준에 규정된 용어는 의미 형상은"may 군대 철수를 위한 최종 표준의 미래 revisions"에.)은 제외됩니다.마찬가지로 암묵적 함수 선언(선언되지 않은 함수를 사용)은 C++에서는 허용되지 않으며 1999년부터 C에서는 유효하지 않습니다.
  • C에서 매개변수가 없는 기능 프로토타입입니다.int foo();는 파라미터가 지정되지 않았음을 나타냅니다.따라서 이러한 함수를 하나 이상의 인수를 사용하여 호출하는 것은 합법적입니다.foo(42, "hello world")이와는 대조적으로 C++에서 인수 없는 함수 프로토타입은 함수가 인수를 받지 않는 것을 의미하며, 인수와 함께 함수를 호출하는 것은 잘못된 형식입니다.C에서 인수를 사용하지 않는 함수를 선언하는 올바른 방법은 다음과 같이 'void'를 사용하는 것입니다.int foo(void);C++에서도 유효합니다.빈 기능 프로토타입은 C89에서와 같이 C99에서 사용되지 않는 기능입니다.
  • C와 C++에서는 모두 네스트된 것을 정의할 수 있습니다.struct타입은 다르지만 스코프는 다르게 해석됩니다.C++에서는 네스트되어 있습니다.struct외부 범위/범위 내에서만 정의됩니다.struct반면 C에서는 내부 구조가 외부 구조 외부에 정의됩니다.
  • C는 허용한다.struct,union,그리고.enumC++는 그렇지 않은 반면, 유형들은 기능 프로토타입에 선언해야 합니다.

C99C11은 C++에 표준 C++에 포함되지 않은 몇 가지 추가 기능을 추가하였습니다.예를 들어 복잡한 번호, 가변 길이 어레이는 C11에서는 옵션 확장으로 지정되어 있습니다.또한 유연한 어레이 멤버, restrict 키워드, 어레이 파라미터 한정자, 복합 리터럴, de 등입니다.부호 이니셜라이저

  • 를 사용한 복잡한 산술float complex그리고.double complex기본 데이터 유형이 C99 표준에 추가되었습니다._Complex키워드 및complex편리성 매크로C++에서는 복소수 클래스를 사용하여 복소수 계산을 수행할 수 있지만 두 가지 방법은 코드 호환성이 없습니다.(단,[14] C++11 이후의 표준에서는 바이너리 호환성이 필요합니다).
  • 가변 길이 배열이 기능에 의해 컴파일되지 않은 시간이 발생할 수 있습니다.size of 연산자.[15]
    무효 후우(size_t x, 인트 a[*]);  // VLA 선언 무효 후우(size_t x, 인트 a[x])  {     인쇄물(%zu\n", 크기 a); // size of(int*)와 동일      s[x * 2];     인쇄물(%zu\n", 크기 s); // x*2 인쇄 } 
  • 여러 멤버를 포함하는 C99 구조 유형의 마지막 멤버는 플렉시블 어레이 멤버일 수 있습니다.유연한 어레이 멤버는 길이가 지정되지 않은 어레이의 구문 형식을 취합니다.이는 가변 길이 어레이와 유사한 용도로 사용되지만 VLA는 유형 정의에 표시할 수 없습니다.또한 VLA와 달리 유연한 어레이 멤버의 크기는 정의되어 있지 않습니다.ISO C++에는 이러한 기능이 없습니다.예:
    구조 X {     인트 n, m;      바이트 수[]; } 
  • restrict C99에서 정의된 유형 한정자는 C++03 표준에는 포함되어 있지 않지만 GNU 컴파일러 컬렉션,[16] Microsoft Visual C++, 인텔 C++ 컴파일러 등 대부분의 메인스트림 컴파일러는 확장과 같은 기능을 제공합니다.
  • 함수의 배열 매개 변수 한정자는 C에서 지원되지만 C++에서는 지원되지 않습니다.
    인트 후우(인트 a[컨스턴트]);     // int *const a에 상당합니다. 인트 막대기( s[정적인 5]); // s가 최소 5자 이상임을 주석으로 나타냅니다. 
  • C의 복합 리터럴의 기능은 C++11의 목록 초기화 구문에 의해 삽입형 및 사용자 정의 유형으로 일반화되지만 구문적 및 의미적 차이가 있습니다.
    구조 X a = (구조 X){4, 6};  // C++ 의 등가치는 X{4, 6} 입니다.C99에서 사용되는 C 구문 형식은 GCC 및 Clang C++ 컴파일러의 확장으로 지원됩니다. 후우(&(구조 X){4, 6});         // 객체는 스택에 할당되어 있으며 해당 주소는 함수에 전달될 수 있습니다.이것은 C++에서는 지원되지 않습니다.  한다면 (메모리(d, (인트 []){8, 6, 7, 5, 3, 0, 9}, n) == 0) {} // C++의 등가물은 숫자 = int []를 사용합니다. if ( memcmp (d, digits {8, 6, 7, 5, 3, 0, 9} , n) == 0 ) { } 
  • 어레이의 지정 이니셜라이저는 C:에서만 유효합니다.
     s[20] = { [0] = 'a', [8] = 'g' };  // C++가 아닌 C에서 허용 
  • 반환되지 않는 함수는 다음 명령을 사용하여 주석을 달 수 있습니다.noreturn C는 고유 키워드를 사용하는 반면, C는 고유 키워드를 사용합니다.

C++ 에서는, 새로운 기능을 서포트하기 위해서, 다수의 키워드가 추가되고 있습니다.이것에 의해, C++ 로 무효인 식별자에 이러한 키워드를 사용하는 C 코드가 렌더링 됩니다.예를 들어 다음과 같습니다.

구조 템플릿  {     인트 신규;     구조 템플릿* 학급; }; 
는 유효한 C 코드입니다만, 키워드 때문에 C++ 컴파일러에 의해 거부됩니다.template,new그리고.class예약되어 있습니다.

C와 C++에서 다르게 동작하는 구성

C와 C++ 모두에서 유효하지만 두 언어에서 다른 결과를 생성하는 구문 구조가 몇 가지 있습니다.

  • 다음과 같은 문자 리터럴'a'종류intC타입의charC++로, 즉sizeof 'a'일반적으로 두 언어에서 다른 결과를 얻을 수 있습니다.C++ 에서는, 다음과 같이 됩니다.1단, C에서는sizeof(int)이 유형 차이의 또 다른 결과로서 C에서는'a'의 유무에 관계없이, 항상 서명이 있는 표현입니다.char는 부호 있는 타입 또는 부호 없는 타입입니다만, C++ 의 경우는 컴파일러 실장 마다 다릅니다.
  • C++는 네임스페이스 범위에 내부 링크를 할당합니다.const명시적으로 선언되지 않는 한 변수extern단, C의 경우와 달리extern는 모든 파일 범위 엔티티의 기본값입니다.실제로 이것은 동일한 C 코드와 C++ 코드 간의 사일런트 의미 변경을 초래하지 않고 컴파일 시간 또는 링크 오류를 초래한다는 점에 유의하십시오.
  • C에서 인라인 함수를 사용하려면 정확하게1개의 변환 유닛에 extern 키워드를 사용하여 수동으로 함수의 프로토타입 선언을 추가하여 비인쇄 버전이 링크되어 있는지 확인해야 합니다.단, C++는 자동으로 처리합니다.보다 상세하게 말하면, C는 두 종류의 기능 정의를 구별한다: 통상적인 외부 정의(여기서extern명시적으로 사용) 및 인라인 정의입니다.한편, C++ 에서는 인라인 함수에 대한 인라인 정의만 제공됩니다.C에서 인라인 정의는 하나의 외부 정의와 다른 변환 단위에서 동일한 함수의 내부 및 인라인 정의를 가진 동일한 프로그램에서 공존할 수 있다는 점에서 내부(즉 정적) 정의와 유사합니다.이는 함수의 연결과는 별개의 고려사항이지만 독립적인 고려사항은 아니다.C 컴파일러는 같은 함수의 인라인 정의와 외부 정의 중 하나를 선택할 수 있습니다.단, C++는 외부 링크가 있는 함수가 선언된 경우inline임의의 변환 유닛에서 사용되는 모든 변환 유닛에서 선언(따라서 정의)해야 하며 ODR에 따라 해당 함수의 정의가 모두 동일해야 합니다.스태틱 인라인 함수는 C와 C++에서 동일하게 동작합니다.
  • C99와 C++는 모두 부울 타입입니다. bool상수가 있는true그리고.false단, 정의 방법이 다릅니다.C++에서는bool임베디드 타입으로 예약된 키워드입니다.새로운 키워드인 C99에서는_Bool는 새로운 부울타입으로 도입되었습니다.머리글stdbool.h매크로 제공bool,true그리고.false로 정의되어 있다_Bool,1그리고.0,각각 다음과 같다.그러므로,true그리고.false활자가 있다int주식회사.

이전 섹션과 다른 몇 가지 차이점을 이용하여 양쪽 언어로 컴파일되지만 동작은 다른 코드를 작성할 수도 있습니다.예를 들어, 다음 함수는 C와 C++의 다른 값을 반환합니다.

외부 인트 T;  인트 크기(무효) {     구조 T {  인트 i;  인트 j;  };          돌아가다 크기(T);     /* C: 반환 크기(int) * C++: 반환 크기(구조 T) */ } 

이는 C가 다음을 요구하기 때문입니다.struct구조 태그 앞에 (그리고)sizeof(T)변수를 참조하지만 C++를 사용하면 변수를 생략할 수 있습니다(따라서).sizeof(T)암묵적인 것을 참조하다typedef)의 경우 결과가 다르다는 점에 주의해 주십시오.extern선언은 함수 내부에 배치됩니다.그러면 함수 스코프에 같은 이름의 식별자가 존재하면 암묵적인 의미가 억제됩니다.typedefC++에 대해서 유효하게 하고, C와 C++에 대해서 같은 결과가 됩니다.또한 위의 예에서 모호성은 괄호를 사용하여sizeof교환입니다.사용.sizeof T예상할 수 있다T타입이 아닌 식이기 때문에 C++로 컴파일 할 수 없습니다.

C와 C++ 코드의 링크

C와 C++는 소스 호환성을 크게 유지하고 있지만 각각의 컴파일러가 생성하는 오브젝트 파일은 C와 C++ 코드를 혼재시킬 때 나타나는 중요한 차이를 가질 수 있습니다.특히:

  • C 컴파일러는 C++ 컴파일러와 [17]달리 망글 기호를 명명하지 않습니다.
  • 컴파일러와 아키텍처에 따라서는 호출 규칙이 두 언어 간에 다를 도 있습니다.

이러한 이유로 C++ 코드가 C 함수를 호출하기 위해foo(), C++ 코드는 프로토타입이어야 합니다. foo()와 함께extern "C"마찬가지로 C 코드가 C++ 함수를 호출하는 경우bar(), C++ 코드bar()로 신고해야 한다.extern "C".

C와 C++의 호환성을 유지하기 위한 헤더 파일의 일반적인 방법은 선언을extern "C"헤더 [18]범위:

/* 헤더 파일 foo.h */ #ifdef __cplusplus/* C++ 컴파일러인 경우 C link*/ 를 사용합니다. 외부 'C' { #엔디프  /* 이 함수는 C링크를 가져옵니다*/ 무효 후우();   구조 막대기 { /* ... */ };  #ifdef __cplusplus/* C++ 컴파일러의 경우는, C링크를 종료합니다.* / } #엔디프 

C와 C++ 링크의 차이와 호출 규약은 함수 포인터를 사용하는 코드에 미묘한 영향을 미칠 수도 있습니다.일부 컴파일러는 함수 포인터가 선언된 경우 작동하지 않는 코드를 생성합니다.extern "C"선언되지 않은 C++ 함수를 가리키다extern "C"를 클릭합니다.[19]

예를 들어 다음과 같은 코드가 있습니다.

무효 my_function(기능)(); 외부 'C' 무효 후우(무효 (*fn_ptr)(무효));  무효 막대기() {    후우(my_function(기능)); } 

Sun Microsystems의 C++ 컴파일러를 사용하면 다음 경고가 나타납니다.

 $ 참조 -c 시험.참조  "test.cc",  6: 경고 (시대착오주의): 공식적인. 논쟁 fn_ptr  유형  외부 'C' 무효(*)()  불러 로. 후우(외부 'C' 무효(*)())  존재 통과된  무효(*)(). 

그 이유는my_function()C 링크 및 호출 규약에 의해 선언되지 않고 C 함수에 전달됩니다.foo().

레퍼런스

  1. ^ a b 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). p. 4. Archived (PDF) from the original on 16 August 2012. Retrieved 12 August 2009.
  2. ^ B.Stroustrup. "C and C++: Siblings. The C/C++ Users Journal. July 2002" (PDF). Retrieved 17 March 2019.
  3. ^ "Bjarne Stroustrup's FAQ – Is C a subset of C++?". Retrieved 22 September 2019.
  4. ^ B. Stroustrup. "C and C++: A Case for Compatibility. The C/C++ Users Journal. August 2002" (PDF). Archived (PDF) from the original on 22 July 2012. Retrieved 18 August 2013.
  5. ^ 국제 표준의 근거—프로그래밍 언어C 2016년 6월 6일 Wayback Machine, 개정 5.10(2003년 4월).
  6. ^ "C Dialect Options - Using the GNU Compiler Collection (GCC)". gnu.org. Archived from the original on 26 March 2014.
  7. ^ "N4659: Working Draft, Standard for Programming Language C++" (PDF). §Annex C.1. Archived (PDF) from the original on 7 December 2017. ('명시적 이니셜라이저 또는 암묵적 이니셜라이저를 사용하여 선언을 건너뛰는 것은 무효입니다(블록 전체가 입력되지 않은 것을 제외).…이 단순한 컴파일 타임 룰에 의해, C++는, 초기화된 변수가 범위내에 있는 경우, 확실히 초기화가 끝난 것을 확인합니다.")
  8. ^ "N4659: Working Draft, Standard for Programming Language C++" (PDF). §Annex C.1. Archived (PDF) from the original on 7 December 2017.
  9. ^ "IBM Knowledge Center". ibm.com.
  10. ^ "FAQ > Casting malloc - Cprogramming.com". faq.cprogramming.com. Archived from the original on 5 April 2007.
  11. ^ "4.4a — Explicit type conversion (casting)". 16 April 2015. Archived from the original on 25 September 2016.
  12. ^ "longjmp - C++ Reference". www.cplusplus.com. Archived from the original on 19 May 2018.
  13. ^ "2011 ISO C draft standard" (PDF).
  14. ^ "std::complex - cppreference.com". en.cppreference.com. Archived from the original on 15 July 2017.
  15. ^ "Incompatibilities Between ISO C and ISO C++". Archived from the original on 9 April 2006.
  16. ^ 제한 포인터 2016년 8월 6일 GCC(Gnu 컴파일러 컬렉션)를 사용하여 웨이백 머신에 보관
  17. ^ "IBM Knowledge Center". ibm.com.
  18. ^ "IBM Knowledge Center". ibm.com.
  19. ^ "Oracle Documentation". Docs.sun.com. Archived from the original on 3 April 2009. Retrieved 18 August 2013.

외부 링크