"역참조"의 두 판 사이의 차이
잔글 |
|||
(사용자 2명의 중간 판 5개는 보이지 않습니다) | |||
1번째 줄: | 1번째 줄: | ||
− | '''역참조'''란 프로그래밍에서 | + | '''역참조'''(dereference)란 프로그래밍에서 [[데이터]]가 저장된 [[주소]]로 가서, 그 주소에 해당하는 데이터 값에 접근하는 것을 말한다. [[포인터]](pointer)는 데이터가 저장된 주소값을 가리키지만, 역참조는 그 반대로 주소를 통해 데이터에 접근한다. |
== 개요 == | == 개요 == | ||
− | 역참조는 값에 직접 접근하는 것이 아니라 [[주소]]를 이용해 간접적으로 접근하는 것이다. 그래서 | + | 역참조는 값에 직접 접근하는 것이 아니라 [[주소]]를 이용해 간접적으로 접근하는 것이다. 그래서 [[간접연산자]]라고도 한다. 이제까지 [[함수]]에서 [[매개변수]]를 통해 [[인자]]를 전달하는 등 모든 데이터를 복사해서 썼다면, 역참조를 하면 원본에 접근 가능하다. 즉 컴퓨터 구조에서(CPU, 메모리 등) 데이터를 오랫동안 메모리에 저장할 수 있다. 역참조 원리는 먼저 포인터를 지정하고 있는 메모리 위치로 간 다음 그곳에 지정된 값에 접근하는 원리이다.<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> | ||
+ | |||
+ | 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]
각주[편집]
- ↑ hahehohoo, 〈포인터 이해하기2_참조와 역참조/역 참조 연산자〉, 《티스토리》, 2020-07-18
- ↑ 〈C 언어 코딩 도장:59.2 포인터 연산과 역참조 사용하기〉, 《코딩도장》
- ↑ emplam27, 〈void 포인터의 연산과 역참조〉, 《벨로그》, 2021-01-26
참고자료[편집]
- hahehohoo, 〈포인터 이해하기2_참조와 역참조/역 참조 연산자〉, 《티스토리》, 2020-07-18
- 〈C 언어 코딩 도장:59.2 포인터 연산과 역참조 사용하기〉, 《코딩도장》
- emplam27, 〈void 포인터의 연산과 역참조〉, 《벨로그》, 2021-01-26
같이 보기[편집]