<글을 시작하기에 앞서...>
1. C표준에서는 변수(variable)라는 표현 대신 대상체(object)라는 표현을 사용한다. (같은 뜻이다.)
대상체란 프로그램에서 사용할 값을 저장하는 메모리 상의 공간(영역)이다.
2. 필자는 식별자(identifier)라는 표현 대신 명칭이라는 표현을 사용한다. (마찬가지로 같은 뜻이다.)
🏷️연결 (linkage)
- 명칭과 (프로그램 실행 중에도 메모리 상에 존재하는 언어적 개체인) 함수와 정적 기억수명 대상체 사이의 연결을 의미한다.
- C는 외부 연결, 내부 연결, 연결 없음이라는 세 종류의 연결을 정의하고 있다.
📌1. 외부 연결 (external linkage)
- 어떤 명칭이 외부 연결을 갖고 있다는 것은 그 명칭의 특징과 존재가 해당 프로그램을 구성하는 모든 프로그램 소스로 알려진다는 것을 의미한다.
- 두 개 이상의 프로그램 소스(.c)가 외부 연결을 갖는 명칭 하나를 이용해 하나의 동일한 함수나 대상체를 공유할 수 있다.
- 컴파일-링크 모델에서는 외부 연결을 갖는 명칭은 분리되어 컴파일 되는 각 프로그램 소스가 그 명칭을 볼 수 있도록, 링커에게까지 그 정보가 전달되어야 한다.
📌2. 내부 연결 (interanl linkage)
- 내부 연결을 갖도록 선언된 명칭은 혹시나 다른 프로그램 소스가 선언했을지도 모르는 동일한 명칭과 충돌을 일으키지 않도록, 하나의 프로그램 소스 안에서 고유한 의미로 사용할 수 있도록 허락해준다.
- 따라서 컴파일-링크 모델에서 내부 연결을 갖는 명칭은 링커에게 전달될 필요가 없다.
- 명칭이 내부 연결을 갖기 위해서는 파일 스코프에서 선언되고,
static
기억부류 지정자(storage class specifier)를 선언에 포함시켜야 한다.
- 🖇️cf.
static
기억부류 지정자가 블록 스코프에서 사용되면, 내부 연결이 아닌 정적 기억수명으로 대상체가 선언되었음을 뜻한다.
참고: staic의 두가지 용도
📌3. 연결 없음 (no linkage)
- 말 그대로 연결을 갖고 있지 않는 명칭을 의미한다.
- auto storage duration 대상체와 연결을 갖도록 선언된 명칭은 연결이 없다고 말한다.
- 또는 대상체나 함수에 대한 명칭이 아닌 typedef name인 경우 연결을 갖지 않는다.
🏷️재선언 (redeclaration)
- 재선언이란 스코프와 무관하게, 같은 명칭이 다시 선언되는 것이다.
#include <stdio.h>
static int i;
int main(void)
{
int i;
return 0;
}
- 위 코드에서, 명칭
i
가 재선언된다고 말한다.
- C언어가 구조체의 tag명칭에 대해서 별도로 허락해주는 경우를 제외하면, 근본적으로 어떤 명칭도 같은 스코프 내에서 재선언 될 수 없다.
- 단, 이는 연결을 갖지 않는 명칭에만 적용된다.
- 연결을 가지고 선언되는 명칭(내부 연결이든 외부 연결이든) 몇 번이고 반복해서 재선언 될 수 있다.
- 🖇️cf. 같은 스코프란, 스코프의 시작 위치가 달라도 끝나는 위치가 같은 경우를 의미한다.
- 즉, 같은 블록 스코프에서 연결 없는 명칭은 재선언 될 수 없다.
🏷️연결을 정하는 규칙
- 규칙이 조금 복잡하긴 한데, 어떤 명칭의 연결을 결정하는 기본적인 원리는 첫 선언이 보여준 연결을 그 이후의 선언이 물려받는 것이다.
📌(1) 선언이 extern을 갖고 있는 경우
- ✏️(1-1) 이미 스코프에 그 명칭의 선언이 존재한다.
- 🖍️(1-1-1) 보이는 그 선언이 연결을 갖고 있으면 그 연결을 물려받는다.
- 🖍️(1-1-2) 보이는 그 선언이 연결을 갖고 있지 않으면, 외부연결이 된다.
(연결을 갖고 있지 않으면, 같은 스코프 내에 선언될 수 없다.)
- ✏️(1-2) 처음 선언되는 명칭이면, 그냥 외부연결이 된다.
📌(2) 기억 부류 지정자 없이 선언되는 경우
- ✏️(2-1) 함수를 위한 명칭일 경우, 어떤 스코프에 있든, extern이 존재하는 것처럼 행동한다.
- ✏️(2-2) 대상체를 위한 명칭이 파일 스코프에서 선언된 경우, 외부 연결을 갖는다.
📌(3) 파일 스코프가 아닌 곳에서 대상체를 위한 명칭이 extern없이 선언되는 경우
- ✏️바깥 scope의 동일한 명칭 선언을 숨기고, 새로운 대상체를 위한 no linkage 명칭이 된다.
🏷️정리
- 외부 연결은 프로그램 전체에서, 내부 연결은 하나의 소스 파일 안에서 선언되는 하나의 명칭이 모두 같은 대상체나 함수를 지칭함을 뜻한다.