Code 1.
#include <stdio.h>
int main(void)
{
int a = 42;
printf("%d\\\\n", a);
int a = -42;
printf("%d\\\\n", a);
}
Code 2.
#include <stdio.h>
int a = 42;
int main(void)
{
printf("%d\\\\n", a);
int a = -42;
printf("%d\\\\n", a);
}
Code 3.
#include <stdio.h>
int a = 0;
int main(void)
{
int a = 42;
printf("%d\\\\n", a);
{
int a = -42;
printf("%d\\\\n", a);
}
printf("%d\\\\n", a);
}
Code 4.
#include <stdio.h>
int main(void)
{
struct s {
int s;
};
struct s s = {.s = 42};
printf("%d\\\\n", s.s);
}
Code 5.
#include <stdio.h>
int main(void)
{
typedef struct s {
int s;
} s;
s s = {.s = 42};
printf("%d\\\\n", s.s);
}
위 코드들은 정상 작동할까? 컴파일되지 않으면 그 이유는 무엇이고, 잘 작동한다면 그 이유는 무엇일까?
해답은 C언어의 Identifier(식별자), 그리고 Name Space에 있다.
Note) 이 글은 C99 표준(ISO/IEC 9899)을 바탕으로 설명합니다. 가장 최신 표준인 C23(ISO/IEC 9899:2023)도 추가되는 요소들(constexpr 등)에 대한 설명이 추가될 뿐, 기본 개념은 다르지 않습니다.
C언어 표준은 Identifier를 다음과 같의 정의한다. (C99 6.2.1 Clause 1)
An identifier can denote an object; a function; a tag or a member of a structure, union, or enumeration; a typedef name; a label name; a macro name; or a macro parameter. (...)
식별자(Identifier)는 다음을 가리킨다.
- 객체(object)
- 함수
- 구조체(structure), 공용체(union), 열거체(enumeration)의 태그나 멤버
- typedef
- label
- macro name, macro parameter
여기서 말하는 객체(object)는, C++ 등의 객체 지향 언어에서 말하는 객체와는 다른 개념이다. C언어 표준은 객체에 대해 다음과 같의 정의한다. (C99 3.14)
region of data storage in the execution environment, the contents of which can represent values
실행 환경에서 값을 저장할 수 있는 data storage의 영역
즉, 변수이다.
이어서 오는 부연설명에서, 전처리기(preprocessor)에 의해 치환되는 매크로에 대해서는 논의하지 않는다고 나와 있다. 이 글에서도 앞으로의 논의에서 매크로는 다루지 않는다.