포인터 연산

ORCASUIT·2023년 11월 6일
0

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개의 댓글