programing

C++와 C의 조합 - #ifdef __cplus는 어떻게 동작합니까?

copyandpastes 2022. 7. 4. 23:20
반응형

C++와 C의 조합 - #ifdef __cplus는 어떻게 동작합니까?

레거시 C 코드가 많은 프로젝트를 진행하고 있습니다.레거시 코드도 최종적으로 변환하기 위해 C++로 작성하기 시작했습니다.C와 C++가 어떻게 상호작용하는지 좀 헷갈리네요.C 코드를 로 감싸서 이해했습니다.extern "C"C++ 컴파일러는 C 코드의 이름을 엉망으로 만들지는 않지만 어떻게 구현해야 할지 잘 모르겠습니다.

따라서 각 C 헤더 파일의 맨 위(가드 포함 후)에는

#ifdef __cplusplus
extern "C" {
#endif

그리고 맨 아래에는

#ifdef __cplusplus
}
#endif

둘 사이에는 포함, 유형 및 기능 시제품이 모두 포함되어 있습니다.이 내용을 올바르게 이해하고 있는지 확인하기 위해 몇 가지 질문이 있습니다.

  1. C 헤더 파일 B.h를 포함한 C++ 파일 A.hh와 다른 C 헤더 파일 C.h를 포함하는 경우, 어떻게 작동합니까?컴파일러가 B.H에 들어가면__cplusplus정의되어 있기 때문에, 코드에는extern "C"(그리고__cplusplus이 블록 내에서는 정의되지 않습니다).C.h.에 들어가면__cplusplus정의되지 않고 코드가 로 감싸지지 않습니다.extern "C".이거 맞는건가요?

  2. 코드 조각을 감싸는 데 문제가 있나요?extern "C" { extern "C" { .. } }두 번째는 어떻게 될까요?extern "C"할 수 있을까?

  3. 이 포장지는 .c파일에 넣지 않고 .h파일에만 넣습니다.그러면 어떤 기능에 시제품이 없다면 어떻게 될까요?컴파일러는 그것이 C++ 함수라고 생각합니까?

  4. 또한 C로 표기된 서드파티 코드를 사용하고 있으며, 이 코드에는 이러한 래퍼가 붙어 있지 않습니다.내가 그 라이브러리의 헤더를 넣을 때마다extern "C"#currents 주변입니다.이렇게 하는 게 맞습니까?

  5. 마지막으로, 이것이 좋은 생각일까요?우리가 해야 할 일이 또 있나요?가까운 장래에 C와 C++를 혼합할 예정이므로 모든 베이스에 대응하고 있는지 확인하고 싶습니다.

extern "C"컴파일러가 코드를 읽는 방법은 바뀌지 않습니다.코드가 .c 파일에 있는 경우 C로 컴파일되고 .cpp 파일에 있는 경우 C++로 컴파일됩니다(설정에 이상한 조작을 하지 않는 한).

뭐?extern "C"링크에 영향을 줍니다.C++ 함수는 컴파일 시 이름이 지워집니다.이것이 오버로드를 가능하게 합니다.함수 이름은 파라미터의 유형과 수에 따라 수정되므로 동일한 이름을 가진 두 함수의 기호 이름이 서로 다릅니다.

내부 코드extern "C"아직 C++ 코드입니다.외부 "C" 블록에서 수행할 수 있는 작업에는 제한이 있지만 모두 링크에 관한 것입니다.C 링크로 작성할 수 없는 새로운 기호를 정의할 수 없습니다.이는 예를 들어 클래스나 템플릿이 없음을 의미합니다.

extern "C"블록은 둥지가 좋다.그리고 또extern "C++"만약 당신이 절망적으로 안에 갇힌 자신을 발견한다면extern "C"지역도 있지만 청결의 관점에서 보면 별로 좋은 생각이 아닙니다.

다음으로, 특히 번호부여에 관한 질문입니다.

#1에 대해서: __cplus plus 에서는 정의되어 있습니다.extern "C"블록.하지만 블록들이 깔끔하게 둥지를 틀어야 하기 때문에 이것은 문제가 되지 않는다.

#2에 대해서: __cplusplus는 C++ 컴파일러를 통해 실행되는 모든 컴파일 유닛에 대해 정의됩니다.일반적으로 이것은 .cpp 파일과 해당 .cpp 파일에 포함된 모든 파일을 의미합니다.같은 .h(또는 .hh, .hpp 또는 What-have-you)는 다른 컴파일 유닛에 포함되어 있는 경우 다른 시점에서 C 또는 C++로 해석될 수 있습니다..h 파일의 프로토타입이 C 기호 이름을 참조하도록 하려면 다음과 같이 해야 합니다.extern "C"C++로 해석될 때, 그리고 그들은 C++로 해석되어서는 안 된다.extern "C"C로 해석될 때 -- 즉,#ifdef __cplusplus체크하고 있습니다.

질문 3: 프로토타입이 없는 함수는 .cpp 파일에 있고 내부가 아닌 경우 C++ 링크가 있습니다.extern "C"block. 그래도 괜찮습니다. 왜냐하면 시제품이 없으면 같은 파일 내의 다른 함수에 의해서만 호출될 수 있기 때문입니다.그리고 일반적으로 링크가 어떻게 보이는지는 신경 쓰지 않습니다.왜냐하면 어차피 같은 컴파일 유닛 이외의 다른 함수에 의해 호출될 계획이 없기 때문입니다.

4번은 정확하게 맞혔어요.C 링크(C 컴파일러에 의해 컴파일된 코드 등)를 가진 코드의 헤더를 포함할 경우,extern "C"헤더 -- 그러면 라이브러리와 링크할 수 있습니다. (그렇지 않으면 링크커는 다음과 같은 이름을 가진 함수를 찾을 것입니다.)_Z1hic당신이 찾고 있을 때void h(int, char)

5: 이러한 종류의 혼합이 사용하는 일반적인 이유입니다.extern "C"이런 식으로 하는 것이 나쁘다고는 생각하지 않습니다.자신이 무엇을 하고 있는지 확실히 이해하도록 하세요.

  1. extern "C"의 유무는 변경되지 않습니다.__cplusplus거시적이야 말로 포장된 선언의 연결고리와 이름만 바꿀 뿐이지

  2. 둥지를 틀 수 있다extern "C"꽤 행복하게 블록합니다.

  3. 컴파일 할 경우.c파일을 C++로 하고, 그 이외의 파일에는extern "C"블록, 미포함extern "C"프로토타입은 C++ 함수로 처리됩니다.그것들을 C로 컴파일하면 당연히 모든 것이 C 함수가 됩니다.

  4. 네.

  5. 이 방법으로 C와 C++를 안전하게 혼합할 수 있습니다.

Andrew Shelansky의 훌륭한 답변에 동조하고 약간 동의하지 않는 몇 가지 고차들은 컴파일러가 코드를 읽는 방법을 실제로 바꾸지 않습니다.

함수 프로토타입은 C로 컴파일되므로 다른 파라미터로 동일한 함수명을 오버로드할 수 없습니다.이것은 컴파일러 이름 망글링의 주요 특징 중 하나입니다.이것은 링크의 문제로 설명되고 있습니다만, 실제로는 그렇지 않습니다.컴파일러와 링커 양쪽에서 에러가 발생합니다.

오버로드와 같은 프로토타입 선언의 C++ 기능을 사용하려고 하면 컴파일러 오류가 발생합니다.

선언 주위에 외부 "C" 래퍼가 없고 헤더가 C와 C++ 소스의 혼합에 포함되어 있으면 함수를 찾을 수 없는 것처럼 보이기 때문에 링커 오류가 나중에 발생합니다.

컴파일 C를 C++ 설정으로 사용하지 않는 이유 중 하나는 소스 코드가 더 이상 이식할 수 없다는 것을 의미하기 때문입니다.이 설정은 프로젝트 설정이기 때문에 .c 파일이 다른 프로젝트에 드롭된 경우 c++로 컴파일되지 않습니다.파일 서픽스의 이름을 .cpp로 변경해 주셨으면 합니다.

C와 C++ 어플리케이션 모두 문제없이 C 인터페이스를 사용할 수 있도록 하기 위한 ABI에 관한 것입니다.

C언어는 매우 쉽기 때문에 코드 생성은 GCC, Borland C\C++, MSVC 등 다양한 컴파일러에서 수년간 안정적이었다.

C++가 점점 보급되는 가운데 새로운 C++ 도메인에 많은 것을 추가해야 합니다(예를 들어 Cfront는 필요한 기능을 모두 커버할 수 없기 때문에 AT&T에서 포기되었습니다).템플릿 기능이나 컴파일 타임코드 생성과 같은 컴파일러 벤더는 실제로 C++ 컴파일러와 링커를 개별적으로 실장했지만 실제 ABI는 다른 플랫폼의 C++ 프로그램과 전혀 호환되지 않습니다.

사람들은 여전히 실제 프로그램을 C++에 구현하고 싶어할 수 있지만, 여전히 오래된 C 인터페이스와 ABI를 유지하고 있습니다. 헤더 파일은 컴파일러가 C++ 컴파일러가 아닌 C 컴파일러일 경우 인터페이스 함수에 대해 호환성이 있는/오래된/심플한/쉬운 C ABI를 생성하도록 컴파일러에 지시합니다.

언급URL : https://stackoverflow.com/questions/3789340/combining-c-and-c-how-does-ifdef-cplusplus-work

반응형