Array initialization
초기화 중인 객체가 배열 타입일 때, 초기자는 반드시 (선택적으로 중괄호로 둘러싸인) 문자열 리터럴 이거나 배열 멤버들을 위한 초기값들의 중괄호로 둘러싸인 목록이어야 합니다:
=
string-literal
|
(1) | ||||||||
=
{
expression
,
...
}
|
(2) | (C99 이전) | |||||||
=
{
designator
(선택적)
expression
,
...
}
|
(2) | (C99 이후) | |||||||
=
{
}
|
(3) | (C23 이후) | |||||||
[
constant-expression
]
=
형태의 배열 지정자 사용 가능
(C99부터)
알려진 크기의 배열과 알려지지 않은 크기의 배열은 초기화될 수 있습니다 , 하지만 VLA는 제외 (C99부터) (C23까지) . VLA는 빈 초기화만 가능합니다. (C23부터)
명시적으로 초기화되지 않은 모든 배열 요소는 empty-initialized 됩니다.
목차 |
문자열로부터의 초기화
문자열 리터럴 (선택적으로 중괄호로 둘러싸인)은 일치하는 타입의 배열에 대한 초기화자로 사용될 수 있습니다:
- 일반 문자열 리터럴 및 UTF-8 문자열 리터럴 (C11부터) 은 모든 문자 타입의 배열을 초기화할 수 있습니다 ( char , signed char , unsigned char )
- L-접두사 와이드 문자열 리터럴은 (cv-한정자 무시) wchar_t 와 호환되는 모든 타입의 배열을 초기화하는 데 사용될 수 있습니다
|
(C11부터) |
문자열 리터럴의 연속된 바이트 또는 와이드 문자열 리터럴의 와이드 문자들(종료 널 바이트/문자를 포함)이 배열의 요소들을 초기화합니다:
char str[] = "abc"; // str은 char[4] 타입을 가지며 'a', 'b', 'c', '\0'을 저장함 wchar_t wstr[4] = L"猫"; // str은 wchar_t[4] 타입을 가지며 L'猫', '\0', '\0', '\0'을 저장함
배열의 크기가 알려진 경우, 문자열 리터럴의 크기보다 하나 작을 수 있으며, 이 경우 종료 널 문자는 무시됩니다:
char str[3] = "abc"; // str은 char[3] 타입을 가지며 'a', 'b', 'c'를 보유함
문자열 리터럴을 char * str = "abc" ; 로 직접 접근할 때와 달리, 이러한 배열의 내용은 수정 가능합니다.
중괄호로 둘러싸인 목록으로부터의 초기화
배열이 중괄호로 둘러싸인 초기화자 목록으로 초기화될 때, 목록의 첫 번째 초기화자는 인덱스 0의 배열 요소를 초기화합니다 (지정자가 명시되지 않은 경우) (C99부터) , 그리고 각 후속 초기화자 (지정자가 없는 경우) (C99부터) 는 이전 초기화자에 의해 초기화된 요소보다 하나 더 큰 인덱스의 배열 요소를 초기화합니다.
int x[] = {1,2,3}; // x는 int[3] 타입을 가지며 1,2,3을 보관함 int y[5] = {1,2,3}; // y는 int[5] 타입을 가지며 1,2,3,0,0을 보관함 int z[4] = {1}; // z는 int[4] 타입을 가지며 1,0,0,0을 보관함 int w[3] = {0}; // w는 int[3] 타입을 가지며 모두 0을 보관함
알려진 크기의 배열을 초기화할 때 요소 수보다 많은 초기화자를 제공하는 것은 오류입니다 (문자열 리터럴로 문자 배열을 초기화하는 경우는 제외).
|
지정자는 이후 초기화자가 지정자가 기술하는 배열 요소를 초기화하도록 합니다. 초기화는 지정자가 기술하는 요소 다음 요소부터 순서대로 계속 진행됩니다. int n[5] = {[4]=5,[0]=1,2,3,4}; // holds 1,2,3,4,5 int a[MAX] = { // starts initializing a[0] = 1, a[1] = 3, ... 1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0 }; // for MAX=6, array holds 1,8,6,4,2,0 // for MAX=13, array holds 1,3,5,7,9,0,0,0,8,6,4,2,0 ("sparse array") |
(C99부터) |
알 수 없는 크기의 배열을 초기화할 때, 초기화자가 지정된 가장 큰 첨자가 선언되는 배열의 크기를 결정합니다.
중첩 배열
배열의 요소가 배열, 구조체 또는 공용체인 경우, 중괄호로 묶인 초기화 목록에서 해당 멤버에 대한 유효한 초기화자는 다음과 같이 중괄호를 생략할 수 있다는 점을 제외하고 해당 멤버에 유효한 모든 초기화자입니다:
중첩된 초기화 리스트가 여는 중괄호로 시작하는 경우, 닫는 중괄호까지의 전체 중첩 초기화 리스트가 해당 배열 요소를 초기화합니다:
int y[4][3] = { // 각각 3개의 int를 가진 4개의 배열로 구성된 배열 (4x3 행렬) { 1 }, // 0번 행이 {1, 0, 0}으로 초기화됨 { 0, 1 }, // 1번 행이 {0, 1, 0}으로 초기화됨 { [2]=1 }, // 2번 행이 {0, 0, 1}으로 초기화됨 }; // 3번 행이 {0, 0, 0}으로 초기화됨
중첩된 초기화자가 여는 중괄호로 시작하지 않는 경우, 하위 배열, 구조체 또는 공용체의 요소나 멤버를 설명하기 위해 목록에서 충분한 초기화자만 가져옵니다. 남은 초기화자는 다음 배열 요소를 초기화하는 데 사용됩니다:
int y[4][3] = { // 4개의 3개 int 배열로 구성된 배열 (4x3 행렬) 1, 3, 5, 2, 4, 6, 3, 5, 7 // 행 0이 {1, 3, 5}로 초기화됨 }; // 행 1이 {2, 4, 6}로 초기화됨 // 행 2가 {3, 5, 7}로 초기화됨 // 행 3이 {0, 0, 0}로 초기화됨 struct { int a[3], b; } w[] = { { 1 }, 2 }; // 구조체 배열 // { 1 }은 배열의 요소 #0에 대한 완전한 중괄호 초기화자로 간주됨 // 해당 요소는 { {1, 0, 0}, 0}으로 초기화됨 // 2는 배열의 요소 #1에 대한 첫 번째 초기화자로 간주됨 // 해당 요소는 { {2, 0, 0}, 0}으로 초기화됨
|
배열 지정자는 중첩될 수 있습니다; 중첩된 배열을 위한 대괄호 안의 상수 표현식은 외부 배열을 위한 대괄호 안의 상수 표현식 뒤에 옵니다: int y[4][3] = {[0][0]=1, [1][1]=1, [2][0]=1}; // row 0 initialized to {1, 0, 0} // row 1 initialized to {0, 1, 0} // row 2 initialized to {1, 0, 0} // row 3 initialized to {0, 0, 0} |
(C99부터) |
참고 사항
배열 초기자에서 부분식의 평가 순서 는 C에서 indeterminately sequenced입니다 (그러나 C++11 이후 C++에서는 그렇지 않음):
int n = 1; int a[2] = {n++, n++}; // 지정되지 않았지만 명확히 정의된 동작, // n이 두 번 증가됨 (임의의 순서로) // a가 {1, 2} 또는 {2, 1}로 초기화되는 것 모두 유효함 puts((char[4]){'0'+n} + n++); // 정의되지 않은 동작: // n의 증가와 읽기 연산이 순서가 지정되지 않음
|
C에서는 초기화자의 중괄호 목록이 비어 있을 수 없습니다. C++은 빈 목록을 허용합니다: |
(until C23) |
|
빈 초기화자를 사용하여 배열을 초기화할 수 있습니다: |
(since C23) |
int a[3] = {0}; // 블록 범위 배열을 0으로 초기화하는 유효한 C 및 C++ 방식 int a[3] = {}; // 블록 범위 배열을 0으로 초기화하는 유효한 C++ 방식; C23부터 C에서 유효
다른 모든 초기화 와 마찬가지로, 정적 또는 스레드 지역 저장 기간 을 가진 배열을 초기화할 때는 초기화 리스트의 모든 표현식이 상수 표현식 이어야 합니다:
예제
int main(void) { // 다음 네 개의 배열 선언은 모두 동일합니다 short q1[4][3][2] = { { 1 }, { 2, 3 }, { 4, 5, 6 } }; short q2[4][3][2] = {1, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 4, 5, 6}; short q3[4][3][2] = { { { 1 }, }, { { 2, 3 }, }, { { 4, 5 }, { 6 }, } }; short q4[4][3][2] = {1, [1]=2, 3, [2]=4, 5, 6}; // 열거형 상수와 문자 이름을 지정자를 사용한 배열로 연결할 수 있습니다: enum { RED, GREEN, BLUE }; const char *nm[] = { [RED] = "red", [GREEN] = "green", [BLUE] = "blue", }; }
참고문헌
- C17 표준 (ISO/IEC 9899:2018):
-
- 6.7.9/12-39 초기화 (p: 101-105)
- C11 표준 (ISO/IEC 9899:2011):
-
- 6.7.9/12-38 초기화 (p: 140-144)
- C99 표준 (ISO/IEC 9899:1999):
-
- 6.7.8/12-38 초기화 (p: 126-130)
- C89/C90 표준 (ISO/IEC 9899:1990):
-
- 6.5.7 초기화