n년만에 쓰는 이중포인터

#include <stdio.h>

int main() {
    int i = 42;
    int *p = &i;
    int **pp = &p; 

    printf("i의 값: %d\n", **pp); // 이중 포인터를 통해 i의 값을 출력
    return 0;
}

너무 오랜만에 쓰는 것이어서 긴가민가 했는데, 다행히 예상대로 출력이 되었다.
이 코드를 짤막하게 설명하자면 i라는 변수(그릇)안에 42라는 초기화값을 넣은 뒤 i의 주소를 가리키는 포인터 변수를 선언한다.
그 이후 포인터 변수 p를 참조하게 된다면,주소를 참조하는 것이므로 내부에 있는 i의 값이 출력되는 것이다.
처음에는 그렇다면 참조는 무엇을 하는것인가 싶을 수 있는데, 간단하게 설명하자면 내부를 읽어온다고 생각하면 된다.
그래서 주소를 참조하면 내부의 내용물을 가져오고, 내용물을 참조하면 주소값 즉 그 그릇의 위치를 알려주는 것이다.

포인터를 사용하여 구현하는 링크드 리스트

구조체를 사용하여 구현한 코드이다.
코드는 너무 길어서 네이버 블로그에 따로 올려두었다.

  • 링크드 리스트 코드 게시물

    연습문제 풀기(3.1)

    우선 3.1을 풀면 한가지 재미있는 사실을 알 수 있는데, 마치 (%레지스터명)은 일종의 포인터 기능을 하며 괄호가 없는 경우 단순참조와 유사하게 작동한다는 것이다.
    %rax는 단순한 레지스터 참조 즉 value는 단순참조인 0x100이 담긴다.
    그에 비해 괄호를 씌운다면 주소값에 대한 참조(0x100)이므로 0xff가 value가 되는 것이다.

    extends zero

    좀 더 큰 자료형으로 확장 시 앞에 0을 붙이게 되는데, 이는 프로그램의 안정성 유지와 깊은 관계가 있다.
    예를 들어 8비트에서 16비트로 변환시 0x96을 0x0096으로 바꾸면(부호가 없음)오버플로우를 방지할 수 있다.
    반대로 부호가 없는 unsigned형의 경우 언더플로우에 대한 방지 역시 가능한데, 위에서 말한 예시는 크기가 작아 상관이 없으나 크기가 커질수록 데이터 확장시 일관성을 지키는 것이 중요하다.

    연습문제 풀기(3.4)

  • char to int
    movesbl(%rdi),%eax
    위의 경우 char을 int에 확장하여 %eax레지스터에 저장하는 것이다.
    이 과정에서 bl을 사용한 것은 0을 붙이는 확장을 통하여 바이트를 더블워드인 int로 표현하기 위해서이다.
    movl %eax,($rsi)
    eax에 적재된 내용물을 rsi의 주소에 옮긴다.
    이때 rsi는 두번째 arg로 1st가 사용중이어서 rsi를 사용한 것이다.
    또한 int형이기 때문에 rsi를 사용한 것이다.
  • unsigned char to long
    movzbl(%rdi),%eax
    위와 동일하게 작은 곳에서 큰 곳으로 옮기는 과정이므로 extends zero명령어 내에서 선택을 해야한다.
    (+ 부호가 없는 곳에서 부호가 있는 곳으로 가는 거기 때문에 우선적으로 movzbl을 사용하여 크기를 맞추어준다.) 또한 retrun val에 담겨있던 것을 %rdi즉, 좀 더 큰 것을 저장할 수 있는 1st arg의 레지스터 주소를 찾아 적재시키는 것이다.
    movq %rax,(%rsi)
    위에서 저장한 rsi의 값을 불러온 뒤 return val을 하기 위해 rax에 적재한다.
    또한 long의 경우 위에서 movq를 사용하였으니 동일하게 movq를 해주고,그에 맞는 return크기인 rax를 2st인 rsi에 담는다.
    (다만 의아한 것은 long을 왜 movq로 분리하였는가이지만…)

    연습문제 풀기(3.6)-3.5는 흐름 따라가면 돼서 생략

  • leaq 9(%rdx),%rax
    이건 rdx에 저장된 데이터인 q에 9만큼 더하는 간단한 코드이다.
    괄호가 들어가면 내용물을 불러온다라고 이해하면 편하다.
  • leaq (%rdx,$rbx),%rax
    위와 마찬가지이나, 두 개의 메모리로부터 내용물을 불러오는 지점만 차이가 가 있다.
    p와 q를 가져온 뒤 더해서 rax에 적재시키면 된다.
  • leaq 0xE(,%rdx,3),%rax
    우선 진법을 맞추어 주려면 0xE를 10진법 14로 반환한다.
    이후 %rax = 14 + 3 * %rdx를 치환하는 원리로 계산하면 14+3q라는 답을 도출해잴 수 있다.
  • leaq 6(%rbx,%rdx,7),%rdx
    이 경우 rbx에 담긴 값인 p는 그냥 산술적인 덧셈을 실행하고 7의 경우 rdx와 치환을 시켜 6+p+7q가 정답이 된다.

태그:

카테고리:

업데이트:

댓글남기기