식별자

식별자 (identifier)

변수 이름, 함수 이름, 구조체 태그처럼 코드 안에서 어떤 대상을 가리키는 이름을 식별자라고 해요. C에서는 식별자를 만들 때 지켜야 할 규칙이 있어서, 어떤 문자 조합이 이름으로 쓸 수 있는지 아는 게 먼저예요.

출처: cppreference

본문

식별자는 숫자, 밑줄, 소문자·대문자 라틴 문자, 그리고 \u\U 이스케이프 표기로 지정한 유니코드 문자(C99부터)로 이루어진 임의로 긴 문자 나열이에요. 이때 유니코드 문자는 XID_Continue 클래스에 속해야 해요(C23부터).

유효한 식별자는 숫자가 아닌 문자로 시작해야 해요(라틴 문자, 밑줄, 또는 C23 이전에는 유니코드의 숫자가 아닌 문자, C23부터는 XID_Start 클래스의 유니코드 문자). 식별자는 대소문자를 구분해요(소문자와 대문자는 서로 다른 이름이에요).

모든 식별자는 유니코드 정규화 형식 C(Normalization Form C)를 따라야 해요. (C23부터)

char * \U0001f431 = "cat" ; // supported 
 char * 🐱 = "cat" ; // implementation-defined 
 // (e.g. works with Clang, but not GCC prior to version 10) 
 // both are ill formed in C23. Emoji are not XID_Start characters

(C99부터, C23 이전)

식별자가 나타낼 수 있는 것

식별자는 다음 종류의 대상을 나타낼 수 있어요.

  • 객체(object)
  • 함수
  • 태그(tag): struct, union, 또는 열거형
  • 구조체 또는 공용체의 멤버
  • 열거형 상수
  • typedef 이름
  • 레이블 이름
  • 매크로 이름
  • 매크로 매개변수 이름

예약된 식별자

표준 라이브러리는 자기가 제공하는 모든 식별자를 예약해요. 외부 연결(external linkage)을 갖는 예약 식별자(모든 표준 함수의 이름 등)는 어떤 헤더를 포함하든 항상 예약돼요. 다른 예약 식별자는 연관된 헤더 중 하나를 포함할 때 예약돼요.

다음 식별자들은 구현을 위해, 또는 표준 라이브러리의 향후 사용을 위해 예약되거나 잠재적으로 예약돼 있어요(C23부터).

  • 함수 이름 — 전부 잠재적으로 예약(C23부터)
    • <complex.h>에서 cerf, cerfc, cexp2, cexpm1, clog10, clog1p, clog2, clgamma, ctgamma, csinpi, ccospi, ctanpi, casinpi, cacospi, catanpi, ccompoundn, cpown, cpowr, crootn, crsqrt, cexp10m1, cexp10, cexp2m1, clog10p1, clog2p1, clogp1(이상 C23)와 그 -f, -l 접미사 변형(C99부터).
    • is 또는 to 다음에 소문자가 오는, <ctype.h><wctype.h>의 이름(C95부터).
    • str 또는 wcs(C23부터) 다음에 소문자가 오는, <stdlib.h><inttypes.h>의 이름(C23부터).
    • <math.h>에서 cr_로 시작하는 이름(C23부터).
    • wcs 다음에 소문자가 오는 <wchar.h>의 이름(C95부터).
    • atomic_ 다음에 소문자가 오는 <stdatomic.h>의 이름(C11부터).
    • cnd_, mtx_, thrd_, tss_ 다음에 소문자가 오는 <threads.h>의 이름(C11부터).
  • typedef 이름 — 전부 잠재적으로 예약(C23부터)
    • intuint로 시작하고 _t로 끝나는 <stdint.h>의 이름(C99부터).
    • atomic_이나 memory_ 다음에 소문자가 오는 <stdatomic.h>의 이름(C11부터).
    • cnd_, mtx_, thrd_, tss_ 다음에 소문자가 오는 <threads.h>의 이름(C11부터).
  • 매크로 이름
    • E 다음에 숫자 또는 대문자가 오는 <errno.h>의 이름.
    • FE_ 다음에 대문자가 오는 <fenv.h>의 이름(C99부터).
    • DBL_, DEC32_, DEC64_, DEC128_, DEC_, FLT_, LDBL_ 다음에 대문자가 오는 <float.h>의 이름(C23부터 잠재적으로 예약).
    • INTUINT로 시작하고 _MAX, _MIN, _WIDTH(C23부터), 또는 _C로 끝나는 <stdint.h>의 이름(C99부터; C23부터 잠재적으로 예약).
    • PRISCN 다음에 소문자 또는 X가 오는 <inttypes.h>의 이름(C99부터; C23부터 잠재적으로 예약).
    • LC_ 다음에 대문자가 오는 <locale.h>의 이름.
    • FP_ 다음에 대문자가 오는 <math.h>의 이름(C23부터).
    • MATH_ 다음에 대문자가 오는 <math.h>의 이름(C23부터 잠재적으로 예약).
    • SIGSIG_ 다음에 대문자가 오는 <signal.h>의 이름.
    • TIME_ 다음에 대문자가 오는 <time.h>의 이름(C11부터).
    • ATOMIC_ 다음에 대문자가 오는 <stdatomic.h>의 이름(C11부터; C23부터 잠재적으로 예약).
  • 열거형 상수 — 전부 잠재적으로 예약(C23부터)
    • memory_order_ 다음에 소문자가 오는 <stdatomic.h>의 이름(C11부터).
    • cnd_, mtx_, thrd_, tss_ 다음에 소문자가 오는 <threads.h>의 이름(C11부터).

구현 제한

구현은 다음 한계를 넘어서는 번역 단위를 거부할 수 있어요:

내부 식별자 또는 매크로 이름의 유효 선행 문자 31개 · 외부 식별자의 유효 선행 문자 6개 · 하나의 번역 단위에 있는 외부 식별자 511개 · 한 블록에 선언된 블록 스코프 식별자 127개 · 하나의 전처리 번역 단위에 동시 정의된 매크로 식별자 1024개 (C99 이전)
내부 식별자 또는 매크로 이름의 유효 선행 문자 63개 · 외부 식별자의 유효 선행 문자 31개 · 하나의 번역 단위에 있는 외부 식별자 4095개 (C99부터)

더 알아보기

  • 식별자가 어떤 대상을 가리키는지 규칙은 lookup and name spaces 문서에서 확인할 수 있어요.
  • 식별자가 유효한 범위를 정하는 규칙은 scope 문서를 함께 보면 좋아요.