C ++와 C 결합-#ifdef __cplusplus는 어떻게 작동합니까?
레거시 C 코드 가 많은 프로젝트를 진행 중입니다 . 우리는 결국 레거시 코드를 변환하려는 의도로 C ++로 작성하기 시작했습니다. C 와 C ++의 상호 작용 방식에 대해 약간 혼란스러워합니다 . 나는 포장하여 해당 이해 C를 사용하여 코드를 extern "C"
망글하지 않습니다 컴파일러 ++은 C 의 C 코드의 이름을,하지만 난 완전히 확인이 구현하는 방법을 모르겠어요.
따라서 각 C 헤더 파일 의 상단 (포함 가드 후)에는
#ifdef __cplusplus
extern "C" {
#endif
그리고 맨 아래에
#ifdef __cplusplus
}
#endif
이 둘 사이에는 include, typedef 및 함수 프로토 타입이 모두 있습니다. 이것을 올바르게 이해하고 있는지 확인하기 위해 몇 가지 질문이 있습니다.
C 헤더 파일 Bh를 포함하고 다른 C 헤더 파일 Ch 를 포함하는 C ++ 파일 A.hh 가 있으면 어떻게 작동합니까? 컴파일러가 Bh로
__cplusplus
들어갈 때 정의 될 것이므로 코드를 래핑합니다extern "C"
(__cplusplus
이 블록 안에 정의되지 않음). 따라서 Ch로 들어가면__cplusplus
정의되지 않으며 코드가 래핑되지 않습니다extern "C"
. 이 올바른지?코드 조각을 래핑하는 데 문제가
extern "C" { extern "C" { .. } }
있습니까? 두 번째extern "C"
는 무엇을 할 것인가?이 래퍼는 .c 파일 주위에 배치하지 않고 .h 파일에만 배치합니다. 함수에 프로토 타입이 없으면 어떻게됩니까? 컴파일러는 이것이 C ++ 함수라고 생각합니까?
또한 C 로 작성된 타사 코드를 사용하고 있으며 이러한 종류의 래퍼가 없습니다. 해당 라이브러리의 헤더를 포함 할 때마다
extern "C"
#include를 둘러 쌉니다. 이것이 올바른 처리 방법입니까?마지막으로, 이것이 좋은 아이디어입니까? 우리가해야 할 다른 일이 있습니까? 우리는 가까운 미래에 C 와 C ++를 혼합 할 예정이며, 모든 기반을 다룰 것입니다.
extern "C"
컴파일러가 코드를 읽는 방식을 실제로 바꾸지는 않습니다. 코드가 .c 파일에 있으면 C로 컴파일되고 .cpp 파일에 있으면 C ++로 컴파일됩니다 (구성에 이상한 일이없는 한).
extern "C"
연결에 영향을주는 것은 무엇입니까? C ++ 함수는 컴파일 될 때 이름이 엉망이되어 과부하가 가능합니다. 함수 이름은 매개 변수의 유형과 개수에 따라 수정되므로 같은 이름을 가진 두 함수의 심볼 이름이 달라집니다.
내부의 코드 extern "C"
는 여전히 C ++ 코드입니다. extern "C"블록에서 수행 할 수있는 작업에는 제한이 있지만 모두 연결에 관한 것입니다. C 연결로 만들 수없는 새 심볼을 정의 할 수 없습니다. 예를 들어 클래스 나 템플릿이 없음을 의미합니다.
extern "C"
블록이 멋지게 중첩됩니다. 이이기도 extern "C++"
자신이 희망의 안에 갇혀 발견하면 extern "C"
지역, 그러나 그것은 청결 관점에서 그런 좋은 생각이 아니다.
이제 구체적으로 번호가 매겨진 질문과 관련하여 :
# 1과 관련하여 __cplusplus는 extern "C"
블록 내부에서 정의 된 상태를 유지 합니다. 블록이 깔끔하게 중첩되어야하기 때문에 이것은 중요하지 않습니다.
# 2와 관련하여 __cplusplus는 C ++ 컴파일러를 통해 실행되는 모든 컴파일 단위에 대해 정의됩니다. 일반적으로 이는 .cpp 파일과 해당 .cpp 파일에 포함 된 모든 파일을 의미합니다. 다른 컴파일 단위에 포함 된 경우 동일한 .h (또는 .hh 또는 .hpp 또는 what-have-you)를 다른 시간에 C 또는 C ++로 해석 할 수 있습니다. .h 파일의 프로토 타입이 C 기호 이름을 참조하도록하려면 extern "C"
C ++로 해석 될 때 있어야 하고 C extern "C"
로 해석 될 때 없어야합니다 #ifdef __cplusplus
.
질문 # 3에 대답하기 위해 : 프로토 타입이없는 함수는 extern "C"
블록 내부가 아닌 .cpp 파일에 있으면 C ++ 연결을 갖습니다 . 프로토 타입이없는 경우 동일한 파일의 다른 함수에서만 호출 할 수 있으며 일반적으로 해당 함수를 가질 계획이 없기 때문에 링키지의 모양에 신경 쓰지 않기 때문에 좋습니다. 어쨌든 동일한 컴파일 유닛 외부의 어떤 것에 의해 호출됩니다.
# 4의 경우 정확히 알 수 있습니다. C 링크가있는 코드 (예 : C 컴파일러에 의해 컴파일 된 코드)에 extern "C"
대한 헤더를 포함하는 경우 라이브러리와 링크 할 수있는 헤더가 있어야합니다. (그렇지 않으면, 링커는 찾고 _Z1hic
있을 때 와 같은 이름을 가진 함수를 찾고있을 것입니다void h(int, char)
5 : 이런 종류의 믹싱은 사용하는 일반적인 이유 extern "C"
이며, 이런 식으로 잘못하는 것이 보이지 않습니다. 자신이하는 일을 이해해야합니다.
extern "C"
__cplusplus
매크로의 유무를 변경하지 않습니다 . 래핑 된 선언의 연결 및 이름 관리 만 변경합니다.extern "C"
블록을 매우 행복하게 중첩 할 수 있습니다 ..c
파일을 C ++로 컴파일 하면extern "C"
블록에없고extern "C"
프로토 타입이 없는 것은 C ++ 함수로 처리됩니다. C로 컴파일하면 모든 것이 C 함수가됩니다.예
이런 식으로 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는 C & C가 필요한 모든 기능을 처리 할 수 없기 때문에 AT & T에서 포기되었습니다). 같은 템플릿 과거의 기능과 컴파일 타임 코드 생성, 다른 컴파일러가 실제로 별도로 C ++ 컴파일러 및 링커의 실제 구현 한 벤더 실제 ABI를 다른 플랫폼에서 C ++ 프로그램과 전혀 호환되지 않습니다.
사람들은 여전히 C ++로 실제 프로그램을 구현하고 싶지만 평소와 같이 여전히 오래된 C 인터페이스와 ABI를 유지하고 헤더 파일은 extern "C"{} 을 선언 해야하며 컴파일러 는 호환 가능 / 오래된 / 단순 / 쉬운 C ABI를 생성합니다. 컴파일러가 C ++ 컴파일러가 아닌 C 컴파일러 인 경우 인터페이스 함수의 경우
참고 URL : https://stackoverflow.com/questions/3789340/combining-c-and-c-how-does-ifdef-cplusplus-work
'Programing' 카테고리의 다른 글
Vimdiff에서 diff 섹션을 확장 / 축소하는 방법은 무엇입니까? (0) | 2020.03.19 |
---|---|
UIToolbar에서 왼쪽 화살표 버튼 (예 : UINavigationBar의 "뒤로"스타일 만들기) (0) | 2020.03.19 |
반환 값과 Promise.resolve의 차이점은 then ()에서 (0) | 2020.03.19 |
Windows의 Node.js에서 hello.js 파일을 실행하는 방법은 무엇입니까? (0) | 2020.03.19 |
위도 및 경도 데이터를 SQL 데이터베이스에 저장할 때 어떤 데이터 유형을 사용해야합니까? (0) | 2020.03.19 |