포인터 연산

ORCASUIT·2023년 11월 6일

3.8.2 포인터 산술에 대한 설명

포인터와 산술 연산

C언어는 포인터에 산술 연산을 허용합니다. 계산된 값은 포인터가 참조하는 데이터 타입의 크기에 따라 스케일됩니다. 즉, pT 타입 데이터를 가리키는 포인터이고, p의 값이 xp라면, 식 p+i의 값은 xp + L * i가 됩니다. 여기서 L은 데이터 타입 T의 크기입니다.

단항 연산자 '&', '*'

단항 연산자 &*를 사용하면 포인터를 생성하고 역참조할 수 있습니다. 즉, 어떤 객체를 나타내는 표현식 Expr에 대해, &Expr는 그 객체의 주소를 가리키는 포인터입니다. 주소를 나타내는 표현식 AExpr에 대해, *AExpr는 그 주소에 있는 값을 반환합니다. 따라서 Expr*&Expr는 동일합니다.

배열과 포인터의 서브스크립트 연산

배열 참조 A[i]는 식 *(A+i)와 동일합니다. 이는 i번째 배열 원소의 주소를 계산한 다음 해당 메모리 위치에 접근합니다.

예시

정수 배열 E의 시작 주소와 정수 인덱스 i가 각각 레지스터 %rdx%rcx에 저장되어 있다고 가정합니다. 각 표현식의 어셈블리 코드 구현도 함께 나와 있습니다.

  • E: int *, 값 xE, 어셈블리: movl %rdx,%rax
  • E[0]: int, 값 M[xE], 어셈블리: movl (%rdx),%eax
  • E[i]: int, 값 M[xE + 4i], 어셈블리: movl (%rdx,%rcx,4),%eax
  • &E[2]: int *, 값 xE + 8, 어셈블리: leaq 8(%rdx),%rax
  • E+i-1: int *, 값 xE + 4i - 4, 어셈블리: leaq -4(%rdx,%rcx,4),%rax
  • *(E+i-3): int, 값 M[xE + 4i - 12], 어셈블리: movl -12(%rdx,%rcx,4),%eax
  • &E[i]-E: long, 값 i, 어셈블리: movq %rcx,%rax

이 예시에서 배열 값을 반환하는 연산들은 int 타입을 가지고, 따라서 4바이트 연산 (movl)과 레지스터 (%eax)을 사용합니다. 포인터를 반환하는 연산들은 int * 타입을 가지며, 8바이트 연산 (leaq)과 레지스터 (%rax)를 사용합니다. 마지막 예시는 같은 데이터 구조 내에서 두 포인터의 차이를 계산할 수 있음을 보여주며, 결과는 long 타입과 두 주소의 차이를 데이터 타입의 크기로 나눈 값이 됩니다.

이러한 포인터 산술과 관련된 원칙은 메모리 주소와 데이터의 레이아웃을 이해하고, 그것을 효과적으로 활용하고자 할 때 중요합니다.

0개의 댓글