> php教程 > PHP开发 > 본문

C/C++의 extern 키워드에 대한 자세한 설명

高洛峰
풀어 주다: 2016-12-19 14:32:19
원래의
1042명이 탐색했습니다.

1 기본 설명: extern을 변수나 함수 앞에 배치하여 변수나 함수의 정의가 다른 파일에 있음을 나타낼 수 있으며, 컴파일러는 이 변수나 함수를 발견할 때 다른 모듈에서 해당 정의를 찾도록 유도합니다. 또한 링크 지정을 위해 extern을 사용할 수도 있습니다.

즉, extern에는 두 가지 기능이 있습니다. 첫째, 다음과 같이 "C"와 함께 사용되는 경우 extern "C" void fun(int a, int b); 함수 이름 fun을 컴파일할 때 C++ 대신 해당 함수 이름을 번역하려면 C의 규칙을 따르세요. C++의 규칙은 함수 이름을 번역할 때 fun@aBc_int_int#%$ 또는 그 이름을 인식할 수 없을 정도로 변경합니다. 어쩌면 다른 것일 수도 있습니다. 컴파일러마다 다른 방법을 사용하는 이유에 따라 다릅니다. C++에서는 함수 오버로드를 지원하므로 여기서는 이 문제를 너무 많이 논의하지 않겠습니다. 관심이 있으시면 온라인으로 검색해 보시면 만족스러운 설명을 얻으실 수 있을 거라 믿습니다!
둘째, 헤더 파일에서와 같이 변수나 함수를 수정하기 위해 extern을 "C"와 함께 사용하지 않는 경우: extern int g_Int; it 함수는 함수 또는 전역 변수의 범위를 선언하는 것입니다. 선언된 함수 및 변수는 이 모듈이나 다른 모듈에서 사용할 수 있습니다. 즉, 모듈 B(컴파일 단위! ) 모듈(컴파일 단위) A에 정의된 전역 변수나 함수를 참조할 때 모듈 A의 헤더 파일만 포함하면 됩니다. 컴파일 단계에서 모듈 B는 함수나 변수를 찾을 수 없더라도 오류를 보고하지 않습니다. 이 함수는 링크 시 모듈 A에서 생성된 개체 코드에서 찾을 수 있습니다.

2 질문: extern 변수
는 소스 파일 char a[6]
에서 배열을 정의하고 다음 명령문을 사용하여 이를 다른 파일에서 선언합니다. > 죄송합니다만, 괜찮으신가요?
답변 및 분석:
1) 아니요, 프로그램이 실행되면 불법 접근을 알려줍니다. 그 이유는 T 유형에 대한 포인터가 T 유형의 배열과 동일하지 않기 때문입니다. extern char *a는 문자 배열이 아닌 포인터 변수를 선언하므로 실제 정의와 다르기 때문에 런타임 시 불법 접근이 발생합니다. 선언은 extern char a[ ]로 변경되어야 합니다.
2) 예시 분석은 다음과 같습니다. a[] = "abcd"이면 외부 변수 a=0x61626364(abcd의 ASCII 코드 값), *a는 당연히 의미가 없습니다.
분명히 가 가리키는 공백은 다음과 같습니다. a (0x61626364)는 아닙니다. 불법적인 메모리 접근이 발생하기 쉽다는 의미입니다.
3) 이는 extern을 사용할 때 선언 형식을 엄격하게 준수해야 함을 상기시켜줍니다. 실제 프로그래밍에서는 이러한 오류가 흔합니다.
 4) Extern은 변수 선언에 자주 사용되는데, 이 전역 변수를 참조하려면 *.c 파일에 전역 변수를 선언하고 extern을 사용하십시오.

3 문제: extern 함수 프로토타입이 수정될 때

함수 제공자가 함수 프로토타입을 일방적으로 수정하는 경우 사용자가 이를 모르고 원래 extern 선언을 계속 사용하면 컴파일러는 오류를 보고하지 않습니다. 컴파일하는 동안. 그런데 작동 중에 입력 매개변수가 누락되거나 과다하여 시스템 오류가 자주 발생합니다. 이 상황을 어떻게 해결해야 합니까?
답변 및 분석:
현재 업계에는 이 상황을 처리하기 위한 완벽한 솔루션이 없습니다. 일반적인 접근 방식은 공급자가 자체 xxx_pub.h에 외부 인터페이스 선언을 제공하는 것입니다. 호출자는 헤더 파일을 포함하므로 extern 단계가 제거됩니다. 이 오류를 방지하려면.
검에는 두 개의 날이 있습니다. 외부를 적용하려면 상황에 따라 다른 방법을 선택해야 합니다.

4 문제: extern “C”

C++ 환경에서 C 함수를 사용할 때 컴파일러가 obj 모듈에서 C 함수 정의를 찾을 수 없어 링크가 실패하는 경우가 종종 있습니다. 이 상황에 대한 해결책은 무엇입니까?

정답 및 분석:

컴파일 시 함수의 다형성 문제를 해결하기 위해 C++ 언어는 함수 이름과 매개변수를 결합하여 중간 함수 이름을 생성하지만 C 언어는 그렇지 않기 때문에 결과적으로 링크하는 동안 해당 함수를 찾을 수 없습니다. 이때 C 함수는 링크를 위해 extern "C"로 지정해야 합니다. 이는 컴파일러에게 내 이름을 유지하고 중간 함수를 생성하지 말라고 지시합니다. 연결 이름.
 다음은 표준 작성 방법입니다.
//.h 파일의 선두에
#ifdef __cplusplus
#if __cplusplus
extern "C"{
 #endif
#endif/* __cplusplus */ #endif /* __cplusplus */

5 질문: extern 함수 선언
extern이 함수 앞에 배치되어 함수 선언의 일부가 되는 경우를 자주 볼 수 있습니다. 그렇다면 C 언어 키워드 extern은 함수 선언에서 어떤 역할을 합니까? ?
답변 및 분석:
함수 선언에 extern 키워드가 포함된 경우 해당 함수가 다른 소스 파일에 정의될 수 있다는 의미일 뿐이며 다른 효과는 없습니다. 즉, 다음 두 함수 선언 사이에는 뚜렷한 차이가 없습니다.
extern int f(); 및 int f();
물론 이는 여전히 유용합니다. 즉, include "*를 대체하는 것입니다. h" 함수를 선언하기 위해 일부 복잡한 프로젝트에서는 모든 함수 선언 전에 extern 수정을 추가하는 데 더 익숙합니다. 이렇게 하는 이유와 장단점은 다음 예에서 볼 수 있습니다. "extern으로 수정된 전역 변수"

(1) test1.h에 다음 명령문이 있습니다.
#ifndef TEST1H
#define TEST1H
extern char g_str[]; // 전역 변수 g_str 선언
void fun1();
#endif
(2) test1.cpp에서
#include "test1 .h"
char g_str[] = "123456"; // 전역 변수 g_str 정의
void fun1() { cout (3) 위 test1 모듈이고, 컴파일 및 연결이 통과될 수 있습니다. test2 모듈도 있고 g_str을 사용하려면 원본 파일에서 인용하기만 하면 됩니다.
#include "test1.h"

void fun2() { cout 위의 test1과 test2를 동시에 컴파일하고 연결할 수 있습니다. 관심이 있는 경우 test1을 열 수 있습니다. obj에서 "123456" 문자열을 찾을 수 있지만 test2.obj에서는 찾을 수 없습니다. 이는 g_str이 메모리에 하나의 복사본만 있기 때문입니다. test2.obj 컴파일 단위에는 다른 복사본이 필요하지 않습니다. 그렇지 않으면 연결 중에 보고됩니다. 이 오류는 반복된 정의로 인해 발생합니다.
(4) 어떤 사람들은 방지하기 위해 전역 변수의 선언과 정의를 함께 두는 것을 좋아합니다. 위의 test1.h를
extern char g_str[] = " 123456";으로 변경하는 등 정의를 잊어버린 경우 // 이 시간은 no extern
과 동일합니다. 그런 다음 test1.cpp에서 g_str의 정의를 제거합니다. 이번에는 test1과 test2 두 모듈을 컴파일하고 연결하면 연결 오류가 보고됩니다. 이는 전역 변수 g_str의 정의가 test1.cpp 모듈에 포함되어 있기 때문입니다. h이므로 g_str이 한 번 정의되고 test2.cpp에도 test1.h가 포함되어 있으므로 g_str이 다시 정의됩니다. 이때 커넥터는 test1과 test2에서 두 개의 g_str을 찾았습니다. test1.h에 g_str 정의를 넣어야 한다면 test2 코드에서 #include "test1.h"를 제거하고 다음으로 바꾸세요.
extern char g_str[];
void fun2() { cout << g_str << endl; }
이때 컴파일러는 g_str이 외부 컴파일 모듈이라는 것을 알고 있으며, 이 모듈에서는 다시 정의하지 않겠다고 합니다. 매우 안타깝습니다. test2.cpp에서 #include "test1.h"를 사용할 수 없기 때문에 test1.h에 선언된 다른 함수를 사용할 수 없습니다. 단, extern으로 수정되지 않는 한, 이 경우 선언된 함수의 긴 목록이 있습니다. 기능만 있고 헤더 파일의 기능은 외부 사용을 위한 인터페이스를 제공하는 것입니다. 따라서 헤더 파일에서만 선언을 하십시오. 진실은 항상 그렇게 간단합니다.

6. extern 및 static

(1) extern은 변수가 다른 곳에 정의되어 있음을 나타내며 해당 변수를 여기서 사용해야 함을 나타냅니다.
(2) static은 메모리를 할당할 때를 의미합니다. , 변수는 스택이 아닌 정적 영역에 저장됩니다.

정적의 범위는 내부적으로 연결되어 있으며 이는 extern과 다소 반대이며 extern도 분리되어 있습니다. 저장되지만 extern은 다른 개체에서 extern으로 참조할 수 있지만 static은 사용할 수 없습니다. 구체적인 차이점: 우선 static과 extern은 "호환되지 않는" 쌍입니다. static은 변수를 동시에 수정할 수 없습니다. 둘째, static으로 수정된 전역 변수는 동시에 선언되고 정의됩니다. 즉, 헤더 파일에서 전역 변수를 선언하기 위해 static을 사용하는 경우에도 마찬가지입니다. 동시에 정의됩니다. 정적 수정 전역 변수의 역할 도메인은 자체 컴파일 단위만 될 수 있습니다. 즉, "전역"은 이 컴파일 단위에만 유효하며 다른 컴파일 단위는 이를 볼 수 없습니다. :
(1) test1.h:
#ifndef TEST1H
#define TEST1H
static char g_str[] = "123456"
void fun1();
#endif

(2) test1.cpp:
#include "test1.h"
void fun1() { cout (3) test2.cpp
#include "test1.h"
void fun2() { cout << g_str << endl }
test1.obj를 열면 위의 두 컴파일 단위가 성공적으로 연결될 수 있습니다. , 문자열 "123456"을 찾을 수 있고 test2.obj에서도 찾을 수 있습니다. 중복 정의 오류를 보고하지 않고 성공적으로 연결할 수 있는 이유는 동일한 내용을 가지고 있어도 물리적인 데이터가 저장되어 있기 때문입니다. 두 개의 다른 변수에 동일한 값이 할당된 것처럼 주소는 동일하지 않으며 이 두 변수는 각각의 컴파일 단위에서 작동합니다. 어쩌면 당신은 더 진지하게 위의 코드를 추적하고 디버깅한 결과 두 컴파일 단위(test1, test2)의 g_str 메모리 주소가 동일하다는 것을 알게 되므로 정적으로 수정된 변수도 작동할 수 있다고 결론을 내릴 수 있습니다. 대부분의 컴파일러에는 컴파일러가 다양한 모듈을 연결할 때 메모리를 절약하고 실행 효율성이 더 높은 대상 프로그램을 생성한다는 목표를 달성하기 위해 코드에 대한 최적화 기능이 있습니다. 컴파일 단위, 때로는 위의 "123456"과 같이 동일한 내용을 가진 메모리 복사본 하나만 복사합니다. 두 컴파일 단위에 있는 변수는 동일한 내용을 가지므로 연결 시 메모리에 복사본 하나만 존재하게 됩니다. . 이제 위 코드를 다음과 같이 변경하면 컴파일러의 거짓말을 즉시 노출할 수 있습니다.
(1) test1.cpp:
#include "test1.h"
void fun1( )
{
g_str[0] = ''a'';
cout << g_str << endl;
}

(2) test2.cpp
#include "test1.h"
void fun2() { cout << g_str << endl }
(3) void main() {
fun1()
fun2(); // 123456
}
이때 코드를 추적해 보면 두 컴파일 단위의 g_str 주소가 한 곳에서 수정했기 때문에 동일하지 않다는 것을 알 수 있으며, 따라서 컴파일러는 메모리의 원래 모양을 복원해야 하며 메모리에는 두 모듈의 변수에 대한 두 개의 복사본이 있습니다. static은 위와 같은 특성을 가지고 있기 때문에 static 전역 변수를 정의할 때 일반적으로 헤더 파일이 아닌 원본 파일에 배치하여 다른 모듈에 불필요한 정보 오염을 일으키지 않도록 합니다.

7. extern 및 const

C++에서 const에 의해 수정된 전역 상수는 static과 동일한 특성을 갖습니다. 즉, 이 컴파일된 모듈에서만 사용할 수 있지만 const는 다음과 함께 사용할 수 있습니다. extern 이 상수를 extern const char g_str[];
과 같은 다른 컴파일된 모듈에서 사용할 수 있다고 선언한 다음 원본 파일에서 이를 정의하는 것을 잊지 마십시오. const char g_str[] = "123456"; >

그러니까 const 단독으로 사용하면 static과 같지만, extern과 함께 사용하면 extern과 특성이 똑같아요! 따라서 const에 대해서는 별로 할 말이 없습니다. const char* g_str = "123456"은 const char g_str[] = "123465"와 다릅니다. 이전 const는 g_str 대신 char *를 수정합니다. g_str은 상수가 아니며 정의된 전역 변수로 간주됩니다(다른 컴파일 단위에서 사용할 수 있음). 따라서 char*g_str이 const 전역 상수의 규칙을 따르도록 하려면 다음과 같이 const를 정의하는 것이 가장 좋습니다. char* const g_str="123456".



C/C++의 extern 키워드에 대한 더 많은 관련 기사를 보려면 다음을 참고하세요. PHP 중국어 웹사이트!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 추천
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!