programing

외부 "C"는 함수 선언에만 필요합니까?

shortcode 2023. 7. 22. 11:48
반응형

외부 "C"는 함수 선언에만 필요합니까?

저는 C 프로그램에서 호출해야 하는 C++ 함수를 작성했습니다.할 수 C 서 호 가 하 도 하 기 위 해 록 지 습 했 니 정 다 나 는 에 출 능 ▁c 습 니 했 다 지 ▁to 정 나▁specified ▁i 는 ▁from able ▁call ▁make 서 ▁c ▁it 에extern "C"함수 선언에 표시됩니다.그런 다음 C++ 코드를 컴파일했지만 컴파일러(Dignus Systems/C++)는 함수의 이름을 망가트렸습니다.그래서, 그것은 분명히 그것을 존중하지 않았습니다.extern "C".

이 문제를 해결하기 위해, 나는 덧붙였습니다.extern "C"함수 정의에 적용됩니다.이후 컴파일러는 C에서 호출 가능한 함수 이름을 생성했습니다.

엄히말하면밀,면하,extern "C"함수 선언에만 지정하면 됩니다.이것이 맞습니까? (C++ FAQ에는 이에 대한 좋은 예가 있습니다.)함수 정의에도 지정해야 합니까?

다음은 이를 입증하는 예입니다.

/* ---------- */
/* "foo.h"    */
/* ---------- */

#ifdef __cplusplus
extern "C" {
#endif

/* Function declaration */
void foo(int);

#ifdef __cplusplus
}
#endif

/* ---------- */
/* "foo.cpp"  */
/* ---------- */

#include "foo.h"

/* Function definition */
extern "C"               // <---- Is this needed?
void foo(int i) {
  // do something...
}

내 문제는 무언가를 잘못 코딩한 결과이거나 컴파일러 버그를 발견했을 수 있습니다.어떤 경우에도 스택 오버플로를 상담하여 어떤 것이 기술적으로 "올바른" 방법인지 확인하고 싶었습니다.

더'extern "C"선언에 포함되어 있고 정의 컴파일에 이미 표시되어 있는 한 함수 정의에 필요하지 않습니다.이 표준은 구체적으로 다음을 명시합니다(7.5/5 연결 사양).

함수는 명시적인 연결 사양이 확인된 후 연결 사양 없이 선언될 수 있습니다. 이전 선언에서 명시적으로 지정된 연결은 이러한 함수 선언의 영향을 받지 않습니다.

하지만, 저는 일반적으로 '를 넣었습니다.extern "C"정의에서도 마찬가지입니다. 왜냐하면 외부 "C" 연결을 가진 함수이기 때문입니다.은 불필요하고 에 있을 .virtual메소드 오버라이드에 대해) 하지만 저는 그들 중 한 명이 아닙니다.


제가 질문을 잘못 이해한 것 같습니다.어쨌든, 저는 노력했습니다.


// foo.cpp
/* Function definition */

#include "foo.h"

void foo(int i) {
 //do stuff
}
void test(int i)
{
// do stuff
}

// foo.h
#ifdef __cplusplus
extern "C" {
#endif

/* Function declaration */
void foo(int);

#ifdef __cplusplus
}
#endif

void test(int);

사용nm컴파일된 파일에서 기호를 보려면:


linuxuser$ nm foo.o
00000006 T _Z4testi
         U __gxx_personality_v0
00000000 T foo

이는 외부 "C"로 선언된 함수의 이름이 헝클어지지 않으며 정의 시 외부 "C" 키워드가 필요하지 않음을 분명히 시사합니다.
외부 "C" 없이 작성된 모든 C 라이브러리 코드가 필요했다면 C++ 프로그램에서 사용할 수 없었을 것입니다.

방금 이 상황에 직면했습니다...유쾌한 경험이 아닙니다.

다음은 나의 하나에서 선언되었습니다.c파일:

void unused_isr(void) {}
void ADC_IRQHandler(void)     __attribute__ ((weak, alias("unused_isr"))); 

다음 어딘가에서.cpp파일 I 정의:

void ADC_IRQHandler(void) {                                                                                  
    ...
}

그리고 전달 선언을 다음으로 변경하는 것을 잊었습니다.

void ADC_IRQHandler(void);

AD 변환과 관련하여 제가 모든 것을 제대로 하고 있다는 것을 깨닫는 데 시간이 좀 걸렸지만, 정의에 "외부 C"를 추가하는 데 실패했습니다!

extern "C" void ADC_IRQHandler(void) {                                                                                  
    ...
}

특정 상황에서 그것을 정의에 추가하는 습관을 갖는 것이 유용할 수 있는 이유는 단지 제 2센트입니다.

이 부분에 대해서는 제가 조금 전에 비슷한 문제가 있었고 제 머릿속에서 이 부분을 확실히 파악하는 데 시간이 좀 걸렸기 때문에 Brooks Moses만 이 부분을 제대로 건드렸기 때문에 좀 더 명확하게 진술할 필요가 있다고 생각합니다.

요약하면 헤더가 당신을 버릴 수도 있습니다. 컴파일러가 보는 모든 것은 cpp 파일이고 헤더가 외부 "C"와 함께 당신의 cpp에 다시 포함되지 않는다면, CXX 컴파일러가 C 링크, C로 만들기 위해서는 외부 "C"가 cpp 파일 어딘가(정의 또는 다른 선언)에 있어야 합니다.ompiler는 헤더는 신경쓰지 않고 링커만 신경씁니다.

extern "C"정의 주위에는 필요하지 않습니다.선언문 주변에 붙여놓기만 하면 빠져나갈 수 있습니다.당신의 예에서 한 가지 메모는

#ifdef __cplusplus
extern "C" {
#endif

/* Function declaration */
void foo(int);

#ifdef __cplusplus
}
#endif

코드가 전처리기 매크로 "를 찾고 있습니다.__cplusplus".

일반적으로 구현되지만 컴파일러에 따라 정의될 수도 있고 정의되지 않을 수도 있습니다.예제에서는 다음을 사용합니다.extern "C"선언문 주변에서, 하지만 당신은 그곳에서 ""을 확인하지 않습니다.__cplusplus매크로 때문에 당신이 그렇게 했을 때 효과가 있었던 것 같습니다.

아래 설명을 참조하십시오. Standard C++에는 다음이 필요합니다.__cplusplus매크로가 사전 처리기에 의해 정의됩니다.

둘 다 있어야 합니다.컴파일러는 콜 사이트를 컴파일할 때 C 기호 이름과 호출 규칙을 사용해야 하며, 컴파일러는 함수 정의 자체를 컴파일할 때 C 기호 이름을 생성하고 C 호출 규칙을 사용해야 합니다.

정의가 존재하는 번역 단위에서 볼 수 있는 외부-C 선언이 있다면, 외부-C를 정의에서 제외하는 것을 피할 수 있을지도 모릅니다만, 저는 그것을 확실히 모릅니다.

언급URL : https://stackoverflow.com/questions/1380829/is-extern-c-only-required-on-the-function-declaration

반응형