Type
(참고: 산술 타입 에서 대부분의 내장 타입에 대한 상세 정보와 C 라이브러리에서 제공하는 타입 관련 유틸리티 목록 을 확인할 수 있습니다.)
객체 , 함수 , 그리고 표현식 은 타입 이라는 속성을 가지며, 이는 객체에 저장되거나 표현식에 의해 평가되는 이진 값의 해석을 결정합니다.
목차 |
타입 분류
C 타입 시스템은 다음의 타입들로 구성됩니다:
- 타입 void
- 기본 타입
-
- 타입 char
- 부호 있는 정수 타입
-
- 표준: signed char , short , int , long , long long (C99 이후)
|
(C23 이후) |
|
(C99 이후) |
-
- 부호 없는 정수형
-
- 표준: _Bool , (since C99) unsigned char , unsigned short , unsigned int , unsigned long , unsigned long long (since C99)
|
(C23 이후) |
|
(C99 이후) |
-
- 부동 소수점 형식
-
- 실수 부동 소수점 형식: float , double , long double
|
(C23부터) |
|
(C99부터) |
- 파생 타입
| (C11부터) |
위에 나열된 모든 타입에 대해, 한정자의 의미론이 허용하는 경우
const
,
volatile
, 그리고
restrict
한정자들의 하나, 둘, 또는 세 가지 모두의 조합에 해당하는 여러 한정된 버전의 타입이 존재할 수 있습니다.
타입 그룹
- 객체 타입 : 함수 타입이 아닌 모든 타입
- 문자 타입 : char , signed char , unsigned char
- 정수 타입 : char , 부호 있는 정수 타입, 부호 없는 정수 타입, 열거형 타입
- 실수 타입 : 정수 타입과 실수 부동소수점 타입
- 산술 타입 : 정수 타입과 부동소수점 타입
- 스칼라 타입 : 산술 타입, 포인터 타입 , 그리고 nullptr_t (C23부터)
- 집합체 타입 : 배열 타입과 구조체 타입
- 파생 선언자 타입 : 배열 타입, 함수 타입, 그리고 포인터 타입
객체 표현의 바이트 수가
size_t
타입으로 표현 불가능한 완전한 객체 타입을 구성하는 것
(즉,
sizeof
연산자의 결과 타입)
, 포함하여 런타임에 그러한 VLA 타입을 형성하는 것
(C99부터)
은 정의되지 않은 행위입니다.
호환 가능한 타입
C 프로그램에서, 다른 번역 단위 에서 동일한 객체나 함수를 참조하는 선언들은 반드시 동일한 타입을 사용할 필요가 없습니다. 이들은 충분히 유사한 타입, 공식적으로 호환 가능한 타입 으로 알려진 타입만 사용하면 됩니다. 동일한 규칙이 함수 호출과 lvalue 접근에도 적용됩니다; 인수 타입은 매개변수 타입과 호환 가능 해야 하며, lvalue 표현식 타입은 접근되는 객체 타입과 호환 가능 해야 합니다.
타입
T
와
U
가 호환되는 경우는
-
동일한 타입인 경우(동일한 이름 또는
typedef로 도입된 별칭) - 호환되는 비한정 타입의 동일하게 cvr 한정된 버전인 경우
- 포인터 타입이고 호환되는 타입을 가리키는 경우
- 배열 타입이고
-
- 해당 요소 유형이 호환되며,
- 둘 다 고정된 크기를 가질 경우 그 크기가 동일해야 합니다. 참고: 알려지지 않은 경계를 가진 배열은 호환 가능한 요소 유형을 가진 모든 배열과 호환됩니다. VLA는 호환 가능한 요소 유형을 가진 모든 배열과 호환됩니다. (C99부터)
- 둘 다 구조체/공용체/열거형 타입이며,
-
- (C99) 하나가 태그와 함께 선언된 경우, 다른 하나도 동일한 태그로 선언되어야 합니다.
- 둘 다 완전한 타입인 경우, 해당 멤버들은 정확히 같은 수로 존재해야 하며, 호환 가능한 타입으로 선언되고 일치하는 이름을 가져야 합니다.
- 추가적으로, 둘 다 열거형인 경우 해당 멤버들도 동일한 값을 가져야 합니다.
- 추가적으로, 둘 다 구조체나 공용체인 경우,
-
- 해당 멤버들은 동일한 순서로 선언되어야 합니다 (구조체만 해당)
- 해당 비트 필드 는 동일한 너비를 가져야 합니다.
- 하나는 열거형 타입이고 다른 하나는 해당 열거형의 기반 타입입니다
- 함수 타입이며,
-
- 반환 타입이 호환 가능함
- 둘 다 매개변수 목록을 사용하며, 매개변수의 개수(줄임표 사용 포함)가 동일하고, 배열-포인터 및 함수-포인터 타입 조정을 적용하고 최상위 한정자를 제거한 후 해당 매개변수들이 호환 가능한 타입을 가짐
|
(C23까지) |
char 타입은 signed char 와 호환되지 않으며, unsigned char 와도 호환되지 않습니다.
두 선언이 동일한 객체나 함수를 참조하면서 호환되지 않는 타입을 사용하는 경우, 프로그램의 동작은 정의되지 않습니다.
// 번역 단위 1 struct S { int a; }; extern struct S *x; // TU2의 x와 호환되지만 TU3의 x와는 호환되지 않음 // 번역 단위 2 struct S; extern struct S *x; // 두 x 모두와 호환됨 // 번역 단위 3 struct S { float a; }; extern struct S *x; // TU2의 x와 호환되지만 TU1의 x와는 호환되지 않음 // 동작은 정의되지 않음
// 번역 단위 1 #include <stdio.h> struct s { int i; }; // TU3의 s와 호환되지만 TU2의 s와는 호환되지 않음 extern struct s x = {0}; // TU3의 x와 호환됨 extern void f(void); // TU2의 f와 호환됨 int main() { f(); return x.i; } // 번역 단위 2 struct s { float f; }; // TU4의 s와 호환되지만 TU1의 s와는 호환되지 않음 extern struct s y = {3.14}; // TU4의 y와 호환됨 void f() // TU1의 f와 호환됨 { return; } // 번역 단위 3 struct s { int i; }; // TU1의 s와 호환되지만 TU2의 s와는 호환되지 않음 extern struct s x; // TU1의 x와 호환됨 // 번역 단위 4 struct s { float f; }; // TU2의 s와 호환되지만 TU1의 s와는 호환되지 않음 extern struct s y; // TU2의 y와 호환됨 // 동작은 명확히 정의됨: 객체와 함수의 다중 선언만 호환되는 타입을 가져야 하며, 타입 자체는 그럴 필요 없음
참고: C++에는 호환 가능한 타입(compatible types) 개념이 없습니다. 서로 다른 번역 단위(translation units)에서 호환 가능하지만 동일하지 않은 두 타입을 선언하는 C 프로그램은 유효한 C++ 프로그램이 아닙니다.
복합 타입
복합 타입은 호환 가능한 두 타입으로부터 구성될 수 있습니다; 이는 두 타입 모두와 호환되며 다음 조건들을 만족하는 타입입니다:
- 두 타입이 모두 배열 타입인 경우, 다음 규칙이 적용됩니다:
-
- 한 타입이 알려진 상수 크기의 배열인 경우, 합성 타입은 해당 크기의 배열입니다.
|
(C99부터) |
-
- 그렇지 않으면, 두 타입 모두 크기를 알 수 없는 배열이며 합성 타입은 크기를 알 수 없는 배열입니다.
- 합성 타입의 요소 타입은 두 요소 타입의 합성 타입입니다.
|
(C23 이전) |
- 두 타입이 모두 매개변수 타입 목록을 가진 함수 타입인 경우, 합성 매개변수 타입 목록에 있는 각 매개변수의 타입은 해당 매개변수들의 합성 타입입니다.
이러한 규칙들은 두 타입이 파생된 타입들에 대해 재귀적으로 적용됩니다.
// 다음 두 파일 범위 선언이 주어졌을 때: int f(int (*)(), double (*)[3]); int f(int (*)(char *), double (*)[]); // C23: 오류: 'f'에 대한 충돌하는 타입 // 함수에 대한 결과 복합 타입은 다음과 같습니다: int f(int (*)(char *), double (*)[3]);
내부 또는 외부 링크age 를 가진 식별자가 해당 식별자의 이전 선언이 보이는 범위에서 선언된 경우, 이전 선언이 내부 또는 외부 링크age를 지정한다면 나중 선언에서의 식별자 타입은 복합 타입이 됩니다.
불완전 타입
불완전한 형식은 해당 형식의 객체 크기를 결정하기에 충분한 정보가 부족한 객체 형식입니다. 불완전한 형식은 번역 단위의 특정 지점에서 완성될 수 있습니다.
다음 유형이 불완전합니다:
- 타입 void . 이 타입은 완성될 수 없습니다.
- 크기가 알려지지 않은 배열 타입. 크기를 지정하는 이후 선언으로 완성될 수 있습니다.
extern char a[]; // a의 타입은 불완전함 (일반적으로 헤더 파일에 나타남) char a[10]; // a의 타입은 이제 완전함 (일반적으로 소스 파일에 나타남)
- 내용을 알 수 없는 구조체 또는 공용체 유형입니다. 동일한 범위 내에서 나중에 해당 내용을 정의하는 동일한 구조체 또는 공용체 선언으로 완성될 수 있습니다.
struct node { struct node* next; // 이 시점에서 struct node는 불완전합니다 }; // 이 시점에서 struct node는 완전합니다
타입 이름
타입은 선언 이외의 상황에서도 명명되어야 할 수 있습니다. 이러한 상황에서는 타입 이름 이 사용되며, 이는 문법적으로 타입 지정자 와 타입 한정자 목록 뒤에 선언자 가 오는 형태(단일 객체나 함수를 선언할 때 사용하는 방식과 동일 - 선언 참조)와 정확히 같지만, 식별자가 생략된다는 점이 다릅니다:
int n; // int의 선언 sizeof(int); // 타입 이름의 사용 int *a[3]; // int에 대한 3개 포인터 배열의 선언 sizeof(int *[3]); // 타입 이름의 사용 int (*p)[3]; // 3개 int 배열에 대한 포인터 선언 sizeof(int (*)[3]); // 타입 이름의 사용 int (*a)[*] // VLA에 대한 포인터 선언 (함수 매개변수 내) sizeof(int (*)[*]) // 타입 이름의 사용 (함수 매개변수 내) int *f(void); // 함수 선언 sizeof(int *(void)); // 타입 이름의 사용 int (*p)(void); // 함수 포인터 선언 sizeof(int (*)(void)); // 타입 이름의 사용 int (*const a[])(unsigned int, ...) = {0}; // 함수 포인터 배열 sizeof(int (*const [])(unsigned int, ...)); // 타입 이름의 사용
식별자를 둘러싼 불필요한 괄호는 타입 이름에서 의미를 가지며 "매개변수 명세가 없는 함수"를 나타냅니다:
int (n); // n을 int 타입으로 선언 sizeof(int ()); // "int를 반환하는 함수" 타입 사용
타입 이름은 다음과 같은 상황에서 사용됩니다:
| (C99부터) | |
| (C11부터) |
타입 이름은 새로운 타입을 도입할 수 있습니다:
void* p = (void*)(struct X { int i; } *)0; // 캐스트 표현식에서 사용된 타입 이름 "struct X {int i;}*"은 // 새로운 타입 "struct X"를 도입합니다 struct X x = {1}; // struct X는 이제 스코프 내에 있습니다
참고문헌
- C23 표준 (ISO/IEC 9899:2024):
-
- 6.2.5 Types (p: TBD)
-
- 6.2.6 Representations of types (p: TBD)
-
- 6.2.7 Compatible type and composite type (p: TBD)
- C17 표준 (ISO/IEC 9899:2018):
-
- 6.2.5 Types (p: 31-33)
-
- 6.2.6 Representations of types (p: 31-35)
-
- 6.2.7 Compatible type and composite type (p: 35-36)
- C11 표준 (ISO/IEC 9899:2011):
-
- 6.2.5 Types (p: 39-43)
-
- 6.2.6 Representations of types (p: 44-46)
-
- 6.2.7 Compatible type and composite type (p: 47-48)
- C99 표준 (ISO/IEC 9899:1999):
-
- 6.2.5 Types (p: 33-37)
-
- 6.2.6 Representations of types (p: 37-40)
-
- 6.2.7 Compatible type and composite type (p: 40-41)
- C89/C90 표준 (ISO/IEC 9899:1990):
-
- 3.1.2.5 Types
-
- 3.1.2.6 Compatible type and composite type
참고 항목
|
C++ documentation
for
Type
|