배열과 포인터의 관계

MySprtlty·2023년 9월 2일
0

Standard C

목록 보기
18/36

🏷️배열 수식의 데이터 타입 구분하기

  • C언어의 선언은 수식으로부터 왔다.
  • 따라서, 배열 lvalue의 type을 구분하는 것은 쉽다.
  • 🔍ex) int a[2][3][4]
    • a[1]의 타입은?
      • array of 3 array of 4 int
    • a[1][2]의 타입은?
      • array of 4 int

🏷️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한 상태다.
  • ax 둘 중 하나가 포인터(혹은 decay한 배열)이고, 정수면 포인터 연산이 가능하다.

📌int a[2][3][4];

  • a의 type은 array of 2 array of 3 array of 4 int다.

📌int a[2][3][4]; 분석하기

  • a[1][2][3]을 분석해보자.

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]+2a[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]

profile
2Co 4:7

0개의 댓글