Compound literals (since C99)
지정된 유형(구조체, 공용체 또는 배열 유형일 수도 있음)의 이름 없는 객체를 제자리에서 생성합니다.
목차 |
구문
(
storage-class-specifiers
(선택 사항)
(C23부터)
type
)
{
initializer-list
}
|
(C99부터) | ||||||||
(
storage-class-specifiers
(선택 사항)
(C23부터)
type
)
{
initializer-list
,
}
|
(C99부터) | ||||||||
(
storage-class-specifiers
(선택 사항)
type
)
{
}
|
(C23부터) | ||||||||
여기서
| storage-class-specifiers | - | (C23부터) 다음 중 하나만 포함할 수 있는 저장 클래스 지정자 목록: constexpr , static , register , 또는 thread_local |
| type | - | 완전한 객체 타입이나 크기가 알려지지 않은 배열을 지정하는 타입 이름 (VLA는 제외) |
| initializer-list | - | type 객체의 초기화 에 적합한 초기화자 목록 |
설명
복합 리터럴 표현식은 type 으로 지정된 타입의 무명 객체를 생성하고 initializer-list 로 지정된 방식으로 초기화합니다. 지정 초기화자(Designated initializers) 가 허용됩니다.
복합 리터럴의 타입은 type 입니다 (단, type 이 크기를 알 수 없는 배열인 경우는 제외; 이 경우 크기는 배열 초기화 에서와 같이 initializer-list 로부터 추론됩니다).
복합 리터럴의 값 범주는 lvalue 입니다(주소를 취할 수 있음).
| 복합 리터럴이 평가하는 이름 없는 객체는 파일 범위에서 복합 리터럴이 발생하는 경우 정적 저장 기간 을 가지며, 블록 범위에서 복합 리터럴이 발생하는 경우 자동 저장 기간 을 가집니다(이 경우 객체의 수명 은 포함하는 블록의 끝에서 종료됩니다). | (C23 이전) | |||||||||||||||||||||||
복합 리터럴이 함수 본문 외부 및 모든 매개변수 목록 외부에서 평가되면 파일 범위와 연관됩니다. 그렇지 않으면 포함하는 블록과 연관됩니다. 이 연관에 따라 저장 클래스 지정자(비어 있을 수 있음), 타입 이름 및 초기화 목록(있는 경우)은 각각 다음 형식의 파일 범위 또는 블록 범위에서 객체 정의에 대한 유효한 지정자여야 합니다:
|
(C23 이후) | |||||||||||||||||||||||
참고 사항
const로 한정된 문자 또는 와이드 문자 배열 타입의 복합 리터럴은 문자열 리터럴 과 저장 공간을 공유할 수 있습니다.
(const char []){"abc"} == "abc" // 1 또는 0일 수 있으며, 지정되지 않음
각 복합 리터럴은 해당 스코프에서 단일 객체만 생성합니다:
#include <assert.h> int main(void) { struct S { int i; } *p = 0, *q; int j = 0; again: q = p, p = &((struct S){ j++ }); // S 타입의 이름 없는 객체를 생성하고, // 이전에 j가 보유했던 값으로 초기화한 다음, // 이 이름 없는 객체의 주소를 포인터 p에 할당합니다 if (j < 2) goto again; // 참고: 루프를 사용했다면 여기서 범위가 종료되어, // 복합 리터럴의 수명이 끝나 p가 댕글링 포인터가 됩니다 assert(p == q && q->i == 1); }
복합 리터럴은 이름이 없기 때문에, 복합 리터럴은 자기 자신을 참조할 수 없습니다 (이름이 있는 구조체는 자기 자신을 가리키는 포인터를 포함할 수 있습니다).
복합 리터럴의 구문은 캐스트 와 유사하지만, 중요한 차이점은 캐스트는 비 lvalue 표현식인 반면 복합 리터럴은 lvalue라는 점입니다.
예제
#include <stdio.h> int *p = (int[]){2, 4}; // 이름 없는 정적 int[2] 배열을 생성하고 // 배열을 {2, 4} 값으로 초기화하며 // 배열의 첫 번째 요소를 가리키는 포인터 p를 생성 const float *pc = (const float []){1e0, 1e1, 1e2}; // 읽기 전용 복합 리터럴 struct point {double x,y;}; int main(void) { int n = 2, *p = &n; p = (int [2]){*p}; // 이름 없는 자동 int[2] 배열을 생성하고 // 첫 번째 요소를 이전에 *p가 가리키던 값으로 초기화하며 // 두 번째 요소를 0으로 초기화하고 // 첫 번째 요소의 주소를 p에 저장 void drawline1(struct point from, struct point to); void drawline2(struct point *from, struct point *to); drawline1( (struct point){.x=1, .y=1}, // 블록 범위를 가진 두 개의 구조체를 생성하고 (struct point){.x=3, .y=4}); // drawline1을 호출하여 값으로 전달 drawline2( &(struct point){.x=1, .y=1}, // 블록 범위를 가진 두 개의 구조체를 생성하고 &(struct point){.x=3, .y=4}); // drawline2를 호출하여 주소로 전달 } void drawline1(struct point from, struct point to) { printf("drawline1: `from` @ %p {%.2f, %.2f}, `to` @ %p {%.2f, %.2f}\n", (void*)&from, from.x, from.y, (void*)&to, to.x, to.y); } void drawline2(struct point *from, struct point *to) { printf("drawline2: `from` @ %p {%.2f, %.2f}, `to` @ %p {%.2f, %.2f}\n", (void*)from, from->x, from->y, (void*)to, to->x, to->y); }
가능한 출력:
drawline1: `from` @ 0x7ffd24facea0 {1.00, 1.00}, `to` @ 0x7ffd24face90 {3.00, 4.00}
drawline2: `from` @ 0x7ffd24facec0 {1.00, 1.00}, `to` @ 0x7ffd24faced0 {3.00, 4.00}
참고문헌
- C23 표준 (ISO/IEC 9899:2024):
-
- 6.5.2.5 복합 리터럴 (p: 77-80)
- C17 표준 (ISO/IEC 9899:2018):
-
- 6.5.2.5 복합 리터럴 (p: 61-63)
- C11 표준 (ISO/IEC 9899:2011):
-
- 6.5.2.5 복합 리터럴 (p: 85-87)
- C99 표준 (ISO/IEC 9899:1999):
-
- 6.5.2.5 복합 리터럴 (p: 75-77)