🏷️배열 수식의 데이터 타입 구분하기
- C언어의 선언은 수식으로부터 왔다.
- 따라서, 배열 lvalue의 type을 구분하는 것은 쉽다.
- 🔍ex)
int a[2][3][4]
a[1]
의 타입은?
- array of 3 array of 4 int
a[1][2]
의 타입은?
🏷️Decay
- 배열 lvalue가 수식에서 사용되면 첫 번째 요소를 가리키는 포인터 값으로 Decay한다.
- Decay라고 불리는 이유는 배열의 요소의 개수(사이즈) 데이터를 잃어버리기 때문이다.
- 즉,
a[1]
의 데이터 타입인 array of 3 array of 4 int에서 배열의 첫번 째 요소를 가리키는 pointer to array of 4 int타입의 포인터값으로 바뀐다.
- 이때 요소의 개수인 3을 잃어버리게 된다.
- 이를 일반화하면
a[x][y][z]...
가 배열일때, a[x][y]
가 수식에서 사용되면, &a[x][y][0]
로 decay한다.
- 다만 다음 문맥에서는 제외이다.
size of
의 피연산자
&
피연산자
- 문자형 배열을 초기화하는 문자열 상수인 경우
- 빠른 이해를 위해 배열 lvalue는 첫 번째 요소를 가리키는 포인터라고 생각하면 편하다.
- 그러나 사실은 decay된 포인터값이라는 사실을 언제나 기억하고 있어야 한다.
🏷️Array Subscripting Operator
- 첨자 지정 연산자(
[]
)는 원래 포인터에 적용되는 연산자다.
- 첨자 지정 수식
a[x]
는 *(a+x)
포인터 연산으로 정의되어 있다.
- 이때
a
는 포인터값으로 decay한 상태다.
a
와 x
둘 중 하나가 포인터(혹은 decay한 배열)이고, 정수면 포인터 연산이 가능하다.
📌int a[2][3][4];
a
의 type은 array of 2 array of 3 array of 4 int다.
📌int a[2][3][4];
분석하기
1. a[1][2][3]
2. = *(*(*(a+1)+2)+3)
a
는 pointer to array of 3 array of 4 int, 즉 a[0]
를 가리키는 포인터값으로 decay한다. (a
는 배열 lvalue다.)
a + 1
포인터 연산을 수행한다.
a
는 array of 3 array of 4 int를 가리키는 포인터값이기에 +1
연산을 하면 a[1]
을 가리키는 포인터값이 된다.
(포인터가 가리키는 대상체의 사이즈*정수 만큼 더해지므로)
- 그 포인터 값에 간접 지정 연산을 하면
a[1]
을 지정하는 lvalue가 된다.
3. = *(*(a[1]+2)+3)
a[1]
은 배열이기 때문에 다시 a[1][0]
요소를 가리키는 포인터값으로 decay한다.
- 따라서
a[1]+2
연산은 포인터 연산이 된다.
a[1]
의 데이터 타입은 pointer to array of 4 int다.
- 따라서
a[1]+2
는 a[1][2]
를 가리키는 포인터값이 된다.
- 그 포인터 값에 간접 지정 연산을 하면
a[1][2]
를 지정하는 lvalue가 된다.
4. = *(a[1][2]+3)
a[1][2]
는 배열이기 때문에 다시 a[1][2][0]
요소를 가리키는 포인터값으로 decay한다.
a[1][2]
의 타입은 pointer to int다.
a[1][2]+3
은 따라서 a[1][2][3]
을 가리키는 포인터값이 된다.
- 거기에 간접 지정 연산을 하면
a[1][2][3]
을 가리키는 lvalue가 된다.
5. = a[1][2][3]