검수요청.png검수요청.png

"역참조"의 두 판 사이의 차이

해시넷
이동: 둘러보기, 검색
잔글
 
(사용자 2명의 중간 판 5개는 보이지 않습니다)
1번째 줄: 1번째 줄:
'''역참조'''란 프로그래밍에서 데이터가 저장된 [[주소]]로 가서, 그 주소에 해당하는 데이터 값에 접근하는 것을 말한다. [[포인터]](pointer)는 데이터가 저장된 주소값을 가리키지만, 역참조는 그 반대로 주소를 통해 데이터에 접근한다.
+
'''역참조'''(dereference)란 프로그래밍에서 [[데이터]]가 저장된 [[주소]]로 가서, 그 주소에 해당하는 데이터 값에 접근하는 것을 말한다. [[포인터]](pointer)는 데이터가 저장된 주소값을 가리키지만, 역참조는 그 반대로 주소를 통해 데이터에 접근한다.
  
 
== 개요 ==
 
== 개요 ==
역참조는 값에 직접 접근하는 것이 아니라 [[주소]]를 이용해 간접적으로 접근하는 것이다. 그래서 '간접연산자'라고도 한다. 이제까지 [[함수]]에서 [[매개변수]]를 통해 [[인자]]를 전달하는 등 모든 데이터를 복사해서 썼다면, 역참조를 하면 원본에 접근 가능하다. 즉 컴퓨터 구조에서(CPU, 메모리 등) 데이터를 오랫동안 메모리에 저장할 수 있다.
+
역참조는 값에 직접 접근하는 것이 아니라 [[주소]]를 이용해 간접적으로 접근하는 것이다. 그래서 [[간접연산자]]라고도 한다. 이제까지 [[함수]]에서 [[매개변수]]를 통해 [[인자]]를 전달하는 등 모든 데이터를 복사해서 썼다면, 역참조를 하면 원본에 접근 가능하다. 즉 컴퓨터 구조에서(CPU, 메모리 등) 데이터를 오랫동안 메모리에 저장할 수 있다. 역참조 원리는 먼저 포인터를 지정하고 있는 메모리 위치로 간 다음 그곳에 지정된 값에 접근하는 원리이다.<ref>hahehohoo, 〈[https://bite-sized-learning.tistory.com/265 포인터 이해하기2_참조와 역참조/역 참조 연산자]〉, 《티스토리》, 2020-07-18</ref>
 
 
* '''역참조 원리'''
 
:* 1. 포인터를 지정하고 있는 메모리 위치로 간다.
 
:* 2. 그곳에 저장된 값에 접근한다.<ref>hahehohoo, 〈[https://bite-sized-learning.tistory.com/265 포인터 이해하기2_참조와 역참조/역 참조 연산자]〉, 《티스토리》, 2020-07-18</ref>
 
  
 
== 예제 ==
 
== 예제 ==
포인터 연산으로 조작한 메모리 주소도 역참조 연산을 사용하여 메모리에 접근할 수 있다. 다음 코드를 살펴보겠다.
+
포인터 연산으로 조작한 메모리 주소도 역참조 연산을 사용하여 메모리에 접근할 수 있다.  
 
  #include <stdio.h>
 
  #include <stdio.h>
  
33번째 줄: 29번째 줄:
 
  22
 
  22
 
  33
 
  33
 +
 
numPtrB에는 numPtrA에 1을 더해서 4바이트만큼 순방향으로 이동한 메모리 주소를 저장했고, numPtrC에는 numPtrA에 2를 더해서 8바이트만큼 순방향으로 이동한 메모리 주소를 저장했다.
 
numPtrB에는 numPtrA에 1을 더해서 4바이트만큼 순방향으로 이동한 메모리 주소를 저장했고, numPtrC에는 numPtrA에 2를 더해서 8바이트만큼 순방향으로 이동한 메모리 주소를 저장했다.
 +
 
  numPtrB = numPtrA + 1;    // 포인터 연산. numPtrA + 4바이트
 
  numPtrB = numPtrA + 1;    // 포인터 연산. numPtrA + 4바이트
 
  numPtrC = numPtrA + 2;    // 포인터 연산. numPtrA + 8바이트
 
  numPtrC = numPtrA + 2;    // 포인터 연산. numPtrA + 8바이트
 +
 
numPtr8와 numPtrC도 일반 포인터이므로 * (역참조 연산자)를 사용하여 메모리의 값을 가져올 수 있다. 여기서 포인터 연산은 결과적으로 numPtrA + 1과 numArr[1]은 같고, numPtrA와 numArr[2]는 같다.
 
numPtr8와 numPtrC도 일반 포인터이므로 * (역참조 연산자)를 사용하여 메모리의 값을 가져올 수 있다. 여기서 포인터 연산은 결과적으로 numPtrA + 1과 numArr[1]은 같고, numPtrA와 numArr[2]는 같다.
 +
 
  printf("%d\n", *numPtrB);    // 22: 역참조로 값을 가져옴, numArr[1]과 같음
 
  printf("%d\n", *numPtrB);    // 22: 역참조로 값을 가져옴, numArr[1]과 같음
 
  printf("%d\n", *numPtrC);    // 33: 역참조로 값을 가져옴, numArr[2]와 같음
 
  printf("%d\n", *numPtrC);    // 33: 역참조로 값을 가져옴, numArr[2]와 같음
이번에는 포인터 연산과 동시에 역참조 연산을 사용하는 법을 알아보겠다. 다음과 같이 포인터 연산을 한 부분을 () 괄호로 묶어준 뒤 맨 앞에 *를 붙이면 된다.<ref>〈[https://dojang.io/mod/page/view.php?id=510 C 언어 코딩 도장:59.2 포인터 연산과 역참조 사용하기]〉, 《코딩도장》</ref>
+
 
 +
포인터 연산과 동시에 역참조 연산을 사용하는 법은 다음과 같다. 포인터 연산을 한 부분을 () 괄호로 묶어준 뒤 맨 앞에 *를 붙이면 된다.<ref>〈[https://dojang.io/mod/page/view.php?id=510 C 언어 코딩 도장:59.2 포인터 연산과 역참조 사용하기]〉, 《코딩도장》</ref>
 +
 
 +
struct Object {
 +
    int key;
 +
    int value;
 +
};
 +
 
 +
위 구조체를 이용하여 배열을 만들었을 때의 값이다.
 +
 
 +
struct Object array[3] = { { 1, 10 }, { 2, 20 }, { 3, 30 } };
 +
struct Object *ptr = array;
 +
 
 +
printf("%d\n", ptr->key)   // 1
 +
printf("%d\n", ptr->value)   // 10
 +
printf("%d\n", (ptr + 1)->key)   // 2
 +
printf("%d\n", (ptr + 1)->value)  // 20
 +
printf("%d\n", (ptr + 2)->key)   // 3
 +
printf("%d\n", (ptr + 2)->value)  // 30
 +
 
 +
포인터 연산과 역참조를 이용해 구조체 배열과 동일하게 값을 저장할 수도 있다.
 +
 
 +
void *ptr = malloc(24);
 +
 
 +
*((int *)ptr) = 1;
 +
*((int *)ptr + 1) = 10;
 +
*((int *)ptr + 2) = 2;
 +
*((int *)ptr + 3) = 20;
 +
*((int *)ptr + 4) = 3;
 +
*((int *)ptr + 5) = 30;
 +
 
 +
printf("%d\n", *((char *)ptr));   // 1
 +
printf("%d\n", *((char *)ptr + 4));   // 10
 +
printf("%d\n", *((char *)ptr + 8));   // 2
 +
printf("%d\n", *((char *)ptr + 12));   // 20
 +
printf("%d\n", *((char *)ptr + 16));   // 3
 +
printf("%d\n", *((char *)ptr + 20));   // 30<ref>emplam27, 〈[https://velog.io/@emplam27/C%EC%96%B8%EC%96%B4-void-%ED%8F%AC%EC%9D%B8%ED%84%B0%EC%9D%98-%EC%97%B0%EC%82%B0%EA%B3%BC-%EC%97%AD%EC%B0%B8%EC%A1%B0 void 포인터의 연산과 역참조]〉, 《벨로그》, 2021-01-26</ref>
  
 
{{각주}}
 
{{각주}}
  
 
== 참고자료 ==
 
== 참고자료 ==
 +
* hahehohoo, 〈[https://bite-sized-learning.tistory.com/265 포인터 이해하기2_참조와 역참조/역 참조 연산자]〉, 《티스토리》, 2020-07-18
 +
* 〈[https://dojang.io/mod/page/view.php?id=510 C 언어 코딩 도장:59.2 포인터 연산과 역참조 사용하기]〉, 《코딩도장》
 +
* emplam27, 〈[https://velog.io/@emplam27/C%EC%96%B8%EC%96%B4-void-%ED%8F%AC%EC%9D%B8%ED%84%B0%EC%9D%98-%EC%97%B0%EC%82%B0%EA%B3%BC-%EC%97%AD%EC%B0%B8%EC%A1%B0 void 포인터의 연산과 역참조]〉, 《벨로그》, 2021-01-26
  
 
== 같이 보기 ==
 
== 같이 보기 ==

2021년 10월 8일 (금) 17:46 기준 최신판

역참조(dereference)란 프로그래밍에서 데이터가 저장된 주소로 가서, 그 주소에 해당하는 데이터 값에 접근하는 것을 말한다. 포인터(pointer)는 데이터가 저장된 주소값을 가리키지만, 역참조는 그 반대로 주소를 통해 데이터에 접근한다.

개요[편집]

역참조는 값에 직접 접근하는 것이 아니라 주소를 이용해 간접적으로 접근하는 것이다. 그래서 간접연산자라고도 한다. 이제까지 함수에서 매개변수를 통해 인자를 전달하는 등 모든 데이터를 복사해서 썼다면, 역참조를 하면 원본에 접근 가능하다. 즉 컴퓨터 구조에서(CPU, 메모리 등) 데이터를 오랫동안 메모리에 저장할 수 있다. 역참조 원리는 먼저 포인터를 지정하고 있는 메모리 위치로 간 다음 그곳에 지정된 값에 접근하는 원리이다.[1]

예제[편집]

포인터 연산으로 조작한 메모리 주소도 역참조 연산을 사용하여 메모리에 접근할 수 있다.

#include <stdio.h>
int main()
{
   int numArr[5] = { 11, 22, 33, 44, 55 };
   int *numPtrA;
   int *numPtrB;
   int *numPtrC;

   numPtrA = numArr;    // 배열 첫 번째 요소의 주소를 포인터에 저장

   numPtrB = numPtrA + 1;    // 포인터 연산. numPtrA + 4바이트
   numPtrC = numPtrA + 2;    // 포인터 연산. numPtrA + 8바이트

   printf("%d\n", *numPtrB);    // 22: 역참조로 값을 가져옴, numArr[1]과 같음
   printf("%d\n", *numPtrC);    // 33: 역참조로 값을 가져옴, numArr[2]와 같음

   return 0;
}
실행 결과
22
33

numPtrB에는 numPtrA에 1을 더해서 4바이트만큼 순방향으로 이동한 메모리 주소를 저장했고, numPtrC에는 numPtrA에 2를 더해서 8바이트만큼 순방향으로 이동한 메모리 주소를 저장했다.

numPtrB = numPtrA + 1;    // 포인터 연산. numPtrA + 4바이트
numPtrC = numPtrA + 2;    // 포인터 연산. numPtrA + 8바이트

numPtr8와 numPtrC도 일반 포인터이므로 * (역참조 연산자)를 사용하여 메모리의 값을 가져올 수 있다. 여기서 포인터 연산은 결과적으로 numPtrA + 1과 numArr[1]은 같고, numPtrA와 numArr[2]는 같다.

printf("%d\n", *numPtrB);    // 22: 역참조로 값을 가져옴, numArr[1]과 같음
printf("%d\n", *numPtrC);    // 33: 역참조로 값을 가져옴, numArr[2]와 같음

포인터 연산과 동시에 역참조 연산을 사용하는 법은 다음과 같다. 포인터 연산을 한 부분을 () 괄호로 묶어준 뒤 맨 앞에 *를 붙이면 된다.[2]

struct Object {
   int key;
   int value;
};

위 구조체를 이용하여 배열을 만들었을 때의 값이다.

struct Object array[3] = { { 1, 10 }, { 2, 20 }, { 3, 30 } };
struct Object *ptr = array;
printf("%d\n", ptr->key) 	  // 1
printf("%d\n", ptr->value) 	  // 10
printf("%d\n", (ptr + 1)->key) 	  // 2
printf("%d\n", (ptr + 1)->value)  // 20
printf("%d\n", (ptr + 2)->key)	  // 3
printf("%d\n", (ptr + 2)->value)  // 30

포인터 연산과 역참조를 이용해 구조체 배열과 동일하게 값을 저장할 수도 있다.

void *ptr = malloc(24);
*((int *)ptr) = 1;
*((int *)ptr + 1) = 10;
*((int *)ptr + 2) = 2;
*((int *)ptr + 3) = 20;
*((int *)ptr + 4) = 3;
*((int *)ptr + 5) = 30;
printf("%d\n", *((char *)ptr)); 	  // 1
printf("%d\n", *((char *)ptr + 4)); 	  // 10
printf("%d\n", *((char *)ptr + 8)); 	  // 2
printf("%d\n", *((char *)ptr + 12)); 	  // 20
printf("%d\n", *((char *)ptr + 16)); 	  // 3
printf("%d\n", *((char *)ptr + 20)); 	  // 30[3]

각주[편집]

  1. hahehohoo, 〈포인터 이해하기2_참조와 역참조/역 참조 연산자〉, 《티스토리》, 2020-07-18
  2. C 언어 코딩 도장:59.2 포인터 연산과 역참조 사용하기〉, 《코딩도장》
  3. emplam27, 〈void 포인터의 연산과 역참조〉, 《벨로그》, 2021-01-26

참고자료[편집]

같이 보기[편집]


  검수요청.png검수요청.png 이 역참조 문서는 프로그래밍에 관한 글로서 검토가 필요합니다. 위키 문서는 누구든지 자유롭게 편집할 수 있습니다. [편집]을 눌러 문서 내용을 검토·수정해 주세요.