문제

정적 멤버 함수와 extern "C" 연결 함수의 차이점은 무엇입니까?예를 들어 C++에서 "makecontext"를 사용할 때 함수에 대한 포인터를 전달해야 합니다."makecontext"는 C이므로 Google에서는 extern "C" 링크를 사용할 것을 권장합니다.그러나 나는 정적 작업을 사용하는 것도 가능하다는 것을 알았습니다.나만 운이 좋은 건지...

class X {
   public:
   static void proxy(int i) {}
}
makecontext(..., (void (*)(void)) X::proxy, ...);

extern "C" void proxy(int i) {}
makecontext(..., (void (*)(void)) proxy, ...);

편집하다:정적 멤버 버전이 작동하지 않는(그리고 컴파일러의 버그는 아님) 컴파일러나 아키텍처를 보여줄 수 있습니까?

도움이 되었습니까?

해결책

예, 당신은 운이 좋다 :) Extern "C"는 기본값 인 Extern "C ++"옆에 모든 C ++ 컴파일러가 지원 해야하는 C 언어에 대한 하나의 언어 연결입니다. 컴파일러는 다른 언어 연결을 지원할 수 있습니다. 예를 들어 GCC는 extern "java"를 지원하는 Java 코드와 인터페이스를 허용합니다 (매우 번거롭지 만).

Extern "C"는 컴파일러에 C 코드가 기능을 호출 할 수 있음을 알려줍니다. 구현에 따라 적절한 전화 규칙과 적절한 C 언어 이름 관리 (때로는 "장식")를 포함 할 수는 있지만 필요하지는 않습니다. 정적 멤버 기능이있는 경우 호출 규칙이 C ++ 컴파일러 중 하나입니다. 종종 그들은 해당 플랫폼의 C 컴파일러와 동일합니다. 그래서 나는 당신이 운이 좋다고 말했습니다. C API가 있고 함수 포인터를 전달하는 경우 항상 "C"와 같은 extern "C"로 선언 된 함수에 하나를 더 잘 넣으십시오.

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

함수 포인터 유형에 연결 사양이 포함되어 있지 않지만 오히려

void(*)(void)

링키지는 유형의 필수 부분입니다. typedef없이 직접 표현할 수 없습니다.

extern "C" typedef void(*extern_c_funptr_t)();

Comeau C ++ 컴파일러는 엄격한 모드에서 위의 "C"기능의 주소를 A에 할당하려고하면 오류가 발생합니다. (void(*)()), beause 이것은 C ++ 링키지가있는 함수에 대한 포인터입니다.

다른 팁

참고 extern C 입니다 추천 C/C ++ 상호 운용성의 방법. 여기 마스터가 그것에 대해 이야기하고 있습니다. Eduffy의 답변에 추가하려면 : 글로벌 네임 스페이스의 정적 기능과 변수는 더 이상 사용되지 않습니다. 익명 네임 스페이스를 최소한 사용하십시오.

돌아가다 extern C: Extern C를 사용하지 않으면 정확한 엉망인 이름을 알고 사용해야합니다. 그것은 훨씬 더 고통입니다.

extern "C" C ++ 컴파일러의 이름 Mangling (오버로드에 필요한)을 비활성화합니다.

A.CPP에서 함수를 선언하는 경우 static, B.CPP에서는 찾을 수 없습니다 (C에서 남은 상태이며 익명 네임 스페이스 내에 함수를 배치하는 것과 동일한 효과가 있습니다).

무엇보다 대부분 extern "C" 이는 주로 컴파일러에 따라 다릅니다.많은 플랫폼에서는 선언에 따라 이름 변경 및 호출 규칙을 변경하지만 그 중 어느 것도 표준에 지정되어 있지 않습니다.실제로 표준에서 요구하는 유일한 것은 블록의 코드가 C 함수에서 호출 가능하다는 것입니다.귀하의 특정 질문에 대해 표준은 다음과 같이 말합니다.

언어 연결이 다른 두 가지 함수 유형은 다른 방식으로 동일하더라도 별개의 유형입니다.

이는 다음을 의미합니다. extern "C" void proxy(int i) {} 그리고 /*extern "C++"*/void proxy(int i) {} 다른 유형을 가지며 결과적으로 이러한 함수에 대한 포인터도 다른 유형을 갖게 됩니다.컴파일러는 다음과 같은 훌륭한 작업이 실패하지 않는 것과 같은 이유로 코드를 실패하지 않습니다.

int *foo = (int*)50;
makecontext(..., (void (*)(void)) foo, ...);

이 코드는 일부 플랫폼에서 작동할 수 있지만 이것이 다른 플랫폼에서 작동한다는 의미는 아닙니다(컴파일러가 완전히 표준을 준수하더라도).특정 플랫폼의 작동 방식을 활용하고 있습니다. 이식 가능한 코드 작성에 대해 걱정하지 않는다면 괜찮을 수도 있습니다.

정적 멤버 함수의 경우에는 this 포인터이므로 컴파일러는 이를 멤버가 아닌 함수로 자유롭게 처리할 수 있습니다.다시 말하지만, 여기서의 동작은 플랫폼에 따라 다릅니다.

일반적으로 말하면

스토리지 클래스 :

스토리지 클래스는 변수 또는 식별자의 지속 시간과 범위를 나타내는 데 사용됩니다.

지속:

지속 시간은 변수의 수명을 나타냅니다.

범위:

범위는 변수의 가시성을 나타냅니다.

정적 스토리지 클래스 :

정적 스토리지 클래스는 로컬 변수 인 기능 또는 파일에 대한 식별자를 선언하는 데 사용되며 제어가 선언 된 위치에서 제어가 통과 한 후에 존재하며 값을 유지합니다. 이 스토리지 클래스에는 영구 기간이 있습니다. 이 클래스를 선언 한 변수는 함수의 한 호출에서 다음 콜로 그 값을 유지합니다. 범위는 로컬입니다. 변수는 파일 내에서 전 세계적으로 선언 된 기능으로 만 알려져 있으며 해당 파일 내의 함수에 의해서만 알려져 있거나 보입니다. 이 스토리지 클래스는 변수의 선언이 변수를 0으로 또는 모든 비트로 초기화하도록 보장합니다.

외부 스토리지 클래스 :

외부 스토리지 클래스는 파일의 함수에 알려져 있고 프로그램의 모든 기능에 알려질 수있는 전역 변수를 선언하는 데 사용됩니다. 이 스토리지 클래스에는 영구 기간이 있습니다. 이 클래스의 모든 변수는 다른 과제에 의해 변경 될 때까지 그 값을 유지합니다. 범위는 글로벌입니다. 프로그램 내의 모든 기능으로 변수를 알 수 있거나 볼 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top