([C언어] 17강) 포인터의 포인터와, 포인터의 메모리크기
이번 시간에는 포인터의 포인터를 배워보겠습니다
자 우선 생각해보죠, 우리는 배열은 포인터다 라는 개념을 배웠었습니다
그럼 배열의 요소로 배열을 가지고있는 배열 즉, 2차원배열은 어떻게 이뤄져있는걸까요?
포인터들을 가지고있는 포인터라..
네 바로 포인터의 포인터입니다ㅋㅋ
포인터가 어떤 요소의 주소였다면
포인터의 포인터는 그 주소값이 저장된곳의 주소입니다ㅋㅋㅋ
마치 마트료시카 인형같죠ㅋㅋ
포인터의 포인터형은 다음과 같이 표시합니다
자료형 ** 변수이름;
자 우리는 지난 시간에 콜 바이 벨류와 콜 바이 레퍼런스에 대해 배웠습니다.
그런데 만약에 우리가 배열을 함수의 매개변수로 보내고 싶다면 어떻게 해야할까요?
#include <stdio.h>
int test(int arr[])
{
printf("%d", arr[3]);
}
int main()
{
int a[5] = { 0,1,2,3,4 };
test(a);
}
물론, 이렇게 해도 상관은 없습니다!
그러나 우리는 나름대로의 규칙을 정하도록 하겠습니다.
우리는 이제 배열은 포인터다 라는 개념을 배웠으니 어떻게 해야할까요?
#include <stdio.h>
int test(int * arr)
{
printf("%d", arr[3]);
}
int main()
{
int a[5] = { 0,1,2,3,4 };
test(a);
}
이런식으로 할 수 있겠네요!
하지만 여기에서 꼭 참고해야할 점이 있습니다.
위의 코드에서 test함수 내에서 a배열의 길이를 구하고 싶다고 칩시다.
자 그럼 printf("%d",sizeof(arr) / sizeof(int)); 로 바꿔서
#include <stdio.h>
int test(int* arr)
{
printf("%d", sizeof(arr) / sizeof(int));
}
int main()
{
int a[5] = { 0,1,2,3,4 };
test(a);
}
이렇게 해주면 되겠죠? 한번 해볼까요?
엥??? 분명 우리 배열 크기는 5갠데 왜 1이라고 나오죠..?
정확히는 배열은 포인터지만 포인터는 배열이 아닙니다.
배열은 무조건 요소의 포인터이다는 참이지만
포인터는 무조건 배열이다는 거짓입니다.
배열이 포인터로 바뀌는 순간 자신은 일개의 포인터로 생각할 뿐
자신이 배열이였다는것을 잃어버립니다
그리고 요소의 포인터는 항상 4바이트입니다.
배열이었을 때에는 배열이 sizeof함수를 통해서
"아, 나는 int형이니까 4바이트고 요소가 5개니까 20바이트야!"
이렇게 알려줬었다면
포인터로 바뀌고나서는
"나는 포인터니까 4바이트야, 내 요소? 난 주소일뿐이라 그런거 모르는데?"
이렇게 되는겁니다.
그래서 항상 배열을 매개변수로 함수를 호출할때에는 아래코드처럼 배열의 길이도
매개변수로 보내도록 프로그래밍해주세요!
#include <stdio.h>
int test(int* arr,int length)
{
printf("%d", length);
}
int main()
{
int a[5] = { 0,1,2,3,4 };
test(a, sizeof(a)/sizeof(int));
}
이렇게 하면 test함수도 배열의 길이를 알 수 있겠죠??
그럼 이번엔 포인터의 포인터의 메모리 사이즈를 볼까요?
#include <stdio.h>
int main()
{
int arr[3][3];
int** ptr = arr;
printf("%d", sizeof(ptr));
}
이렇게 해서 실행하면!?
왜 3 x 3 = 9고 int가 4바이트니까.. 9x4=36이어야하는데 대체 왜 4일까요??
아까 말했다싶이 배열을 포인터로 바꾼 순간에 더이상 배열이 아니라 포인터인겁니다
포인터든 포인터의 포인터든 어쨋든 단순히 주소일뿐이기때문에 항상 4바이트입니다.
마지막으로 배열과 2차원배열이 메모리에 쓰이는 방법을 그림으로 나타내자면
arr[8] 배열은 메모리에
이런식으로 저장되지만
arr[4][2] 배열은 메모리에
이렇게 저장된다는 점 꼭 기억해주세요
예를들어
1 2 3 4 5 6
7 8 9 10 11
12 13 14 15 16
이렇게 들어있는 2차원배열은 메모리에
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
이런순서로 들어있게 됩니다.
포인터는 배열이 아닌 포인터일 뿐인데
어떻게 ptr[3] 이런식으로 대괄호로 접근이 가능하죠?
하고 물어보실수 있을것 같은데요
강제로 접근하는겁니다. ptr[3]이라고하면
ptr의 주소갚부터 세칸 뒤에있는 주소에 저장된 값을 가져와라 라는뜻이 됩니다.
ptr[3]이라고 한것과 *(ptr + 3) 은 같은 의미가 됩니다!
이렇게 ptr[3] 이런식으로 대괄호 []로 접근하는 방식을 "랜덤접근"이라고 합니다.
아참! 배열은 포인터이지만 포인터는 배열이 아니다 라는 말은 무슨말인지 이해하기 힘들수도 있어서
더 쉽게 풀어말하자면
연필은 필기도구이지만
필기도구는 연필이 아니다.
라고 보시면 될것같네요!
오늘강좌는 여기서 마치도록 하겠습니다! 수고하셨습니다!