C에는 두 종류의 aggregates가 있다. 바로 array(8장)와 structure(16장. +union, enumeration).
Array(배열)이란?
: 같은 type을 가진 data의 모임
array 선언 : (1)배열 elements의 type과 (2)elements의 개수를 명시해야 한다.
int a[10];
the length of the array는 무조건 (integer) constant expression이어야 한다. (macro OK)(switch문 할 때 그 constant expressions과 같음. variable이나 function call 안됨. const qualifier 붙은 변수도 안됨)
subscripting goes out of range == undefined behavior
Array Declare와 달리 subscripting할 때는 any integer exprssion이 올 수 있다.
int a[3] = { 1, 2, 3 };
The most common form of array initializer is
a list of constant expression exclosed in braces and separated by commas.
C99부턴 상수 아니어도 OK(Section 18.5)
명시된 길이가 아니라 더 짧아도 된다. 그럼 남은 부분은 0으로 assign됨.
하지만 initializer가 아예 비는건 illegal. 배열 길이를 넘는 것도 illegal.
initializer가 있으면, 길이를 안 적어줘도 OK
int a[] = { 1, 2, 3 };
int a[15] = { [2] = 29, [5] = 3 };
Desgnator MUST be constant expression
Desgnator를 지정해주지 않고 쓰는 경우 바로 앞에 있는 놈 다음에 위치에 assign된다.
명시되지 않은 부분은 자동으로 0
sizeof(a) / sizeof(a[0]) : length of the array(for문 같은데서 쓰일 경우 int로 casting해주는게 좋음. 왜냐하면 sizeof 연산하면 size_t type으로 나오기 때문)
An array may have any number of dimensions
Two dimentional array는 컴퓨터 메모리에 row-major order로 저장된다.
ex) m[0,0] / m[0,1] / ... / m[0,7] / m[1,0] / ...
저장은 위 처럼 되지만..
사실 2차원 배열 int a[3][4];
에서 a
는 length가 3이고 element type이 int [4]
인 array이다.(기본)
그리고 각 element가 int [4]
type인 array이다. 즉, 각 elements가 1차원 배열.
: just nest one-dimentional initializers
int a[3][5] = {{ 1, 2, 3, 4, 5},
{ 6, 7, 8, 9, 0},
{ 1, 2, 3, 4, 5}};
inner braces를 빼도 상관없지만, 되도록 안 빼는게 좋음(가독성 떨어지고, 몇몇 컴파일러에선 warning message 보낼 수도 있음)
이차원 배열도 desgnated initializer 사용 가능. (ex. a[5][5] = { [0][1] = 1 };
const char oct_chars[] = { '0', '1', '2', '3', '4', '5', '6', '7' };
array뿐만 아니라 다른 variable에서도 쓰일 수 있지만, array에서 제일 유용하다.
왜냐하면 array가 reference information을 포함할 가능성이 높기 때문이다.
위에서 array declare할 때 constant expressions으로 배열 길이 명시해야 된다고 했는데,
VLA는 배열 길이를 arbitrary expressions으로 표현할 수 있다.
length of VLA는 프로그램이 실행될 때 결정된다. 프로그램이 컴파일 될 때가 아니라..
VLA's restrictions
1. static storage duration이 될 수 없음
2. initializer를 가질 수 없음
subscripting 왜 0부터 시작?
: 컴파일러를 좀 더 간단하게 만듦 + subscripting을 조금 빠르게 해줌
int a[] = { 4, 9, 1, 8 [0] = 5, 7 };
: result -> int a[] = { 5, 7, 1, 8 };
a = b; 형식의 array끼리 assign하는 것은 불가능(애초에 포인터임)