728x90
배열과 포인터의 관계
#include <stdio.h>
int main(void)
{
int arr[3] = { 5, 10, 15 };
int* ptr = arr;
for (int i = 0; i < 3; i++) {
printf("배열 arr[%d] 의 값 : %d\n", i, arr[i]);
}
for (int i = 0; i < 3; i++) {
printf("배열 ptr[%d] 의 값 : %d\n", i, ptr[i]);
}
return 0;
}

- 위 프로그램을 실행시켜 보면 성공적으로 프로그램이 작동하는 것을 알 수 있습니다.
- 포인터라는 녀석은 배열 하나하나의 주소를 똑같이 갖고 있다는 것을 알 수 있습니다.
#include <stdio.h>
int main(void)
{
int arr[3] = { 5, 10, 15 };
int* ptr = arr;
for (int i = 0; i < 3; i++) {
printf("배열 arr[%d] 의 값 : %d\n", i, arr[i]);
}
for (int i = 0; i < 3; i++) {
printf("배열 ptr[%d] 의 값 : %d\n", i, ptr[i]);
}
ptr[0] = 100;
ptr[1] = 200;
ptr[2] = 300;
for (int i = 0; i < 3; i++) {
printf("배열 arr[%d] 의 값 : %d\n", i, arr[i]);
}
for (int i = 0; i < 3; i++) {
printf("배열 ptr[%d] 의 값 : %d\n", i, ptr[i]);
}
return 0;
}

- 그렇다면 조금 더 나아가서 ptr를 활용해서 새로운 값을 넣어주고 다시 한 번 출력해 보겠습니다. 그랬더니 배열 원본의 값도 같이 바뀌었다는 것을 알 수 있습니다. 이것이 의미하는 것은 포인터가 각각 배열의 값들을 가서 바꾸고 있었다는 것을 알 수 있습니다. 즉, 지금 ptr 과 arr 은 똑같은 녀석이라고 할 수 있습니다.
- 한편 arr[i] 는 다음과 같이 표현할 수도 있습니다.
for (int i = 0; i < 3; i++) {
printf("배열 arr[%d] 의 값 : %d\n", i, * (arr + i));
}
- arr 이라는 것 자체는 arr 배열의 첫번째 주소 값을 가지고 있습니다. 그래서 *( ) 를 통해 해당 주소의 값을 가져오게 할 수 있는 것이죠.
이 말이 의미하는 것은 결국 arr == &arr[0] 입니다.
실제로 값을 찍어보면서 확인해보겠습니다.
#include <stdio.h>
int main(void)
{
int arr[3] = { 5, 10, 15 };
int* ptr = arr;
printf("arr 의 주소는 %d이고, arr[0] 의 주소는 %d입니다.\n", arr, &arr[0]);
// *(arr + i) == arr[i] 똑같은 표현이다
// arr 은 arr 배열의 첫번째 값의 주소와 동일하다
// 즉 arr == &arr[0] 이라는 것이다.
return 0;
}

- 실제로 두 주소의 값이 같은 것을 확인할 수 있습니다.
- 또한 *arr 을 출력해보면 5가 출력되는 것을 확인할 수 있습니다.
#include <stdio.h>
int main(void)
{
int arr[3] = { 5, 10, 15 };
int* ptr = arr;
printf("arr 의 주소는 %d이고, arr[0] 의 주소는 %d입니다.\n", arr, &arr[0]);
printf("%d\n", * arr);
printf("%d\n", *&arr[0]); // *&는 아무것도 없는 것과 마찬가지다.
// *(arr + i) == arr[i] 똑같은 표현이다
// arr 은 arr 배열의 첫번째 값의 주소와 동일하다
// 즉 arr == &arr[0] 이라는 것이다.
return 0;
}
- 또 재밌는 점이 하나 있는데, *&arr 에서 *&는 아무것도 안쓴 것과 같다는 점입니다.
- 해당 주소의(&) 값을(*) 가져오라는 의미이기 떄문에 그냥 arr[0] 과 다를게 없다는 의미입니다.
Swap 함수 안과 밖에서의 변수
#include <stdio.h>
void swap(int a, int b);
int main(void)
{
int a = 10;
int b = 20;
// a 와 b 의 값을 바꿔봅시다.
printf("Swap 함수 전 -> a : %d, b : %d\n", a, b);
swap(a, b);
printf("Swap 함수 이후 -> a : %d, b : %d\n", a, b);
return 0;
}
void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
printf("Swap 함수 안에서 -> a : %d, b : %d\n", a, b);
}

- 위 프로그램을 실행시키면 a 변수와 b 변수의 값이 바뀌는 것은 swap 안에서만 이루어지고 main 메서드에서는 적용되지 않는다는 것을 알 수 있습니다.
- 이런 일이 일어나는 이유를 '값에 의한 복사', 영어로는 Call by Value 라고 하는데요. 이것이 의미하는 것은 '값만 복사한다'는 의미입니다. 무슨 말이냐면 main 함수의 a와 b는 swap 함수에서 호출할 때 매개변수로 a 와 b 가 있었는데, 이것은 실제 main 함수의 a 와 b 변수와는 무관하게 이름만 같은 다른 변수이고, 값만 복사해서 사용한다는 것을 의미합니다.
- 그래서 실제로 main 함수의 a 변수와 swap 함수 안의 a 변수의 주소를 찍어보면 다른 것을 알 수 있습니다.
#include <stdio.h>
void swap(int a, int b);
void swap2(int* a, int* b);
int main(void)
{
int a = 10;
int b = 20;
// a 와 b 의 값을 바꿔봅시다.
printf("Swap 함수 전 -> a : %d, b : %d\n", a, b);
swap(a, b);
printf("Swap 함수 이후 -> a : %d, b : %d\n", a, b);
printf("Swap2 함수 이전 -> a : %d, b : %d\n", a, b);
swap2(&a, &b);
printf("Swap2 함수 이후 -> a : %d, b : %d\n", a, b);
return 0;
}
void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
printf("Swap 함수 안에서 -> a : %d, b : %d\n", a, b);
}
// 그런데, 메모리 값의 주소값 자체를 넘기면 어떻게 될까요?
void swap2(int * a, int * b) {
int temp = *a;
*a = *b;
*b = temp;
printf("Swap2 함수 안에서 -> a : %d, b : %d\n", *a, *b);
}

- 재밌는 점은 swap2 함수를 만들고 main 함수에서 사용할 때 a 변수의 주소 값을 넘겨주는 경우입니다.
- 이 경우에는 swap2 함수가 실행된 이후에 main 함수의 변수 a 와 b 의 값이 바뀌어 있는 것을 확인할 수 있습니다.
포인터로 배열 값 변경하기
#include <stdio.h>
void changeArray(int* ptr);
int main(void)
{
int arr2[3] = { 10, 20, 30 };
changeArray(arr2);
for (int i = 0; i < 3; i++) {
printf("%d\n", arr2[i]);
}
}
void changeArray(int* ptr) {
ptr[2] = 50;
}

- 위 프로그램을 실행시키면 arr2 배열의 배열 값 하나를 수정하는 것을 알 수 있습니다.
- 위 프로그램에서 재미있는 점은 arr2 라는 것이 배열의 주소를 정확히 말하자면 &arr2[0] 를 의미하며, 이 주소를 받을 수 있는 매개변수로 포인터 변수인 int* ptr 을 만들어서 ptr[2] = 50 으로 배열의 값을 수정해주었다는 것입니다.
출처 : 유튜브 나도코딩 https://www.youtube.com/watch?v=q6fPjQAzll8
'[언어] > C 언어(나도코딩)' 카테고리의 다른 글
| 포인터 (기본 이해하기) (0) | 2023.06.24 |
|---|---|
| 랜덤(난수) (0) | 2023.06.23 |
| 피라미드 쌓기 { for, while, do while } (0) | 2023.06.23 |
| 경찰서 조서쓰기 { 프로젝트 } (0) | 2023.06.21 |
| 경찰서 조서쓰기 3 { printf, scanf } (0) | 2023.06.21 |