[언어]/C 언어(나도코딩)

배열과 포인터 { 관계, swap(Call by value), 포인터로 배열 값 변경 }

Ben의 프로그램 2023. 6. 27. 19:00
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