External and tentative definitions
번역 단위 의 최상위 수준에서(즉, 전처리 후 모든 #include를 포함한 소스 파일), 모든 C 프로그램은 외부 또는 내부 링크 를 가진 함수와 객체를 선언하는 선언 들의 연속입니다. 이러한 선언들은 어떤 함수 바깥에 나타나기 때문에 외부 선언 으로 알려져 있습니다.
extern int n; // 외부 링크를 가진 외부 선언 int b = 1; // 외부 링크를 가진 외부 정의 static const char *c = "abc"; // 내부 링크를 가진 외부 정의 int f(void) // 외부 링크를 가진 외부 정의 { int a = 1; // 비외부(non-external) return b; } static void x(void) // 내부 링크를 가진 외부 정의 { }
외부 선언으로 선언된 객체는 정적 저장 기간 을 가지므로, auto 또는 register 지정자를 사용할 수 없습니다 (단, auto 는 타입 추론에 사용될 수 있음 (C23부터) . 외부 선언으로 도입된 식별자는 파일 범위 를 가집니다.
목차 |
잠정적 정의
잠정적 정의 는 초기화자가 없는 외부 선언으로, 저장 클래스 지정자 가 없거나 static 지정자를 사용한 경우를 말합니다.
잠정적 정의(tentative definition) 는 정의 역할을 할 수도 있고 하지 않을 수도 있는 선언입니다. 동일한 번역 단위에서 실제 외부 정의가 이전이나 이후에 발견되면, 잠정적 정의는 단순히 선언 역할만 수행합니다.
int i1 = 1; // 정의, 외부 링크 int i1; // 잠정적 정의, i1이 정의되어 있으므로 선언으로 작동 extern int i1; // 선언, 이전 정의를 참조 extern int i2 = 3; // 정의, 외부 링크 int i2; // 잠정적 정의, i2가 정의되어 있으므로 선언으로 작동 extern int i2; // 선언, 외부 링크 정의를 참조
동일한 번역 단위에 정의가 없는 경우, 잠정적 정의는 객체를 빈 초기화 하는 실제 정의 역할을 합니다.
int i3; // 잠정적 정의, 외부 연결 int i3; // 잠정적 정의, 외부 연결 extern int i3; // 선언, 외부 연결 // 이 번역 단위에서 i3는 "int i3 = 0;"으로 정의된 것과 같습니다
extern 선언이 이전 선언에서 식별자의 링크를 이미 확립한 경우 이를 변경하지 않는 것과 달리, 잠정적 정의(tentative definition)는 동일한 식별자의 다른 선언과 링크 측면에서 일치하지 않을 수 있습니다. 동일한 식별자에 대한 두 선언이 유효 범위 내에 존재하고 서로 다른 링크를 가질 경우, 그 동작은 정의되지 않습니다(undefined):
static int i4 = 2; // 정의, 내부 링크 int i4; // 정의되지 않은 동작: 이전 줄과의 링크 불일치 extern int i4; // 선언, 내부 링크 정의를 참조 static int i5; // 잠정적 정의, 내부 링크 int i5; // 정의되지 않은 동작: 이전 줄과의 링크 불일치 extern int i5; // 이전의 내부 링크를 참조
내부 연결을 갖는 잠정적 정의는 완전한 형식을 가져야 합니다.
static int i[]; // 오류, 정적 잠정 정의에서 불완전한 타입 int i[]; // OK, 이 파일에서 나중에 재선언되지 않는 한 int i[1] = {0};과 동일
단일 정의 규칙
각 번역 단위는 내부 링크를 가진 모든 식별자의 외부 정의를 0개 또는 1개 가질 수 있습니다 internal linkage (a static global).
내부 연결성을 가진 식별자가
비 VLA가 아닌,
(C99부터)
sizeof
,
_Alignof
(C11부터)
(C23까지)
,
alignof
(C23부터)
, 또는
typeof
(C23부터)
이외의 어떤 표현식에서 사용된다면, 해당 식별자에 대해 번역 단위 내에 정확히 하나의 외부 정의가 존재해야 합니다.
전체 프로그램은 external linkage 를 갖는 모든 식별자에 대해 0개 또는 1개의 외부 정의를 가질 수 있습니다.
외부 연결을 갖는 식별자가
비-VLA,
(C99부터)
sizeof
,
_Alignof
(C11부터)
(C23까지)
,
alignof
(C23부터)
, 또는
typeof
(C23부터)
이외의 어떤 표현식에서 사용된다면, 해당 식별자에 대한 정확히 하나의 외부 정의가 프로그램 전체에 반드시 존재해야 합니다.
참고 사항
|
서로 다른 번역 단위에 있는 인라인 정의들은 일 정의 규칙(one definition rule)의 제약을 받지 않습니다. 인라인 함수 정의에 대한 자세한 내용은
|
(C99부터) |
저장 기간과 링크 에서 파일 범위 선언에서 extern 키워드의 의미를 참조하십시오
선언과 정의의 차이점에 대해서는 definitions 를 참조하십시오.
잠정적 정의(tentative definitions)는 내부 연결성을 가진 식별자를 미리 선언하는 C89 이전의 다양한 접근 방식들을 표준화하기 위해 고안되었습니다.
참고문헌
- C23 표준 (ISO/IEC 9899:2024):
-
- 6.9 외부 정의 (p: TBD)
- C17 표준 (ISO/IEC 9899:2018):
-
- 6.9 외부 정의 (p: 113-116)
- C11 표준 (ISO/IEC 9899:2011):
-
- 6.9 외부 정의 (p: 155-159)
- C99 표준 (ISO/IEC 9899:1999):
-
- 6.9 외부 정의 (p: 140-144)
- C89/C90 표준 (ISO/IEC 9899:1990):
-
- 3.7 외부 정의