함수 호출 시 전달되는 인자의 값은 매개변수에 복사가 된다.
매개변수로 배열을 선언할 수 없다.
#include <stdio.h>
void ShowArayElem(int* param, int len)
{
int i;
for(i=0; i<len; i++)
printf("%d ", param[i]);
printf("\n");
}
int main(void)
{
int arr1[3] = {1, 2, 3};
int arr2[5] = {4, 5, 6, 7, 8};
ShowArayElem(arr1, sizeof(arr1) / sizeof(int));
ShowArayElem(arr2, sizeof(arr2) / sizeof(int));
return 0;
}
실행결과
1 2 3
4 5 6 7 8
#include <stdio.h>
void ShowArayElem(int* param, int len)
{
int i;
for(i=0; i<len; i++)
printf("%d ", param[i]);
printf("\n");
}
void AddArayElem(int* param, int len, int add)
{
int i;
for(i=0; i<len; i++)
param[i] += add;
}
int main(void)
{
int arr[3] = {1, 2, 3};
AddArayElem(arr, sizeof(arr) / sizeof(int), 1);
ShowArayElem(arr, sizeof(arr) / sizeof(int));
AddArayElem(arr, sizeof(arr) / sizeof(int), 2);
ShowArayElem(arr, sizeof(arr) / sizeof(int));
AddArayElem(arr, sizeof(arr) / sizeof(int), 3);
ShowArayElem(arr, sizeof(arr) / sizeof(int));
return 0;
}
실행결과
2 3 4
4 5 6
7 8 9
void ShowArayElem(int* param, int len){...}
void ShowArayElem(int param[],int len){...}
int param[]과 int* param은 완전히 동일한 선언이다. 그런데 전자의 선언이 배열이 인자로 전달된다는 느낌을 더 강하게 주는 선언이므로, 일반적으로 배열의 주소 값이 인자로 전달될 때에는 int param[] 형태의 선언을 주로 많이 사용한다.
void SimpleAryFunc1(int* arr)
{
int size = sizeof(arr); //변수 size에는 포인터 변수 arr의 크기가 저장
...
}
배열의 주소 값 을 인자로 전달받는 매개변수는 포인터 변수이기 때문에 이를 대상으로 sizeof 연산을 할 경우 배열의 크기가 반환되지 않고 포인터 변수의 크기가 반환된다.
다음 예제는 문제점이 있다.
#include <Stdio.h>
void Swap(int n1, int n2)
{
int temp = n1;
n1 = n2;
n2 = temp;
printf("n1 n2: %d %d \n", n1, n2);
}
int main(void)
{
int num1 = 10;
int num2 = 20;
printf("num1 num2: %d %d \n", num1, num2);
Swap(num1, num2);
printf("num1 num2: %d %d \n", num1, num2);
return 0;
}
실행결과
num1 num2: 10 20
n1 n2: 20 10
num1 num2: 10 20
Swap 함수 내에서는 매개변수 n1과 n2에 저장된 값이 변경되지만, num1과 num2에 저장된 값의 변경으로까지 이어지지는 않는다.
#include <Stdio.h>
void Swap(int* ptr1, int* ptr2)
{
int temp = *ptr1;
*ptr1 = *ptr2;
*ptr2 = temp;
}
int main(void)
{
int num1 = 10;
int num2 = 20;
printf("num1 num2: %d %d \n", num1, num2);
Swap(&num1, &num2);
printf("num1 num2: %d %d \n", num1, num2);
return 0;
}
실행결과
num1 num2: 10 20
num1 num2: 20 10
int main(void)
{
int num;
scanf("%d", &num);
...
}
scanf 함수 호출이 완료되면 변수 num에는 값이 채워진다. 이를 위해서 scanf 함수는 변수 num의 주소 값을 알아야 한다.
int main(void)
{
char str[30];
scanf("%d", str);
...
}
배열 이름 str은 그 자체로 배열의 주소 값이므로 & 연산자를 붙이지 않는다.
Q. 변수 num에 저장된 값의 제곱을 계산하는 함수를 정의하고, 이를 호출하는 main 함수를 작성해보자. 단, 여기서는 다음 두 가지 형태로 함수를 정의해야 한다.
• Call-by-value 기반의 SquareByValue 함수
• Call-by-reference 기반의 SquareByReference 함수
SquareByValue 함수는 인자로 전달된 값의 제곱을 반환해야 하며, SquareByReference 함수는 정수가 저장되어 있는 변수의 주소 값을 인자로 받아서 해당 변수에 저장된 값의 제곱을 그 변수에 다시 저장해야 한다.
Q. 세 변수에 저장된 값을 서로 뒤바꾸는 함수를 정의해보자. 예를 들어서 함수의 이름이 Swap3라 하면, 다음의 형태로 함수가 호출되어야 한다.
Swap3(&numl, &num2, &num3);
그리고 함수호출의 결과로 num1 에 저장된 값은 num2에, num2에 저장된 값은 num3에, 그리고 num3에 저장된 값은 num1 에 저장되어야 한다.
const 선언을 하게 되면, 포인터 변수가 가리키는 변수에 저장된 값을 변경하는 것을 허용하지 않는다.
int main(void)
{
int num = 20;
const int* ptr = #
*ptr = 30; // 컴파일 에러!
num = 40; // 컴파일 성공!
...
}
int* const ptr = #
const 선언이 포인터 변수의 이름 앞에 오게 되면, 포인터 변수는 상수가 된다. 즉, 한번 주소 값이 저장되면 그 값의 변경이 불가능하며, 한번 가리키기 시작한 변수를 끝까지 가리켜야 한다.
const int* const ptr = #
위와 같이 선언을 하게 되면 포인터 변수가 참조하는 대상의 내용을 바꾸는 것도, 포인터 변수가 가리키는 대상을 바꾸는 것도 불가능하다.
*ptr = 20; //컴파일 에러
ptr = &age; //컴파일 에러
Q. 아래에 정의된 함수를 보자. 인자로 전달되는 정보를 참조하여 int형 배열요소 전체를 출력하는 함수이다.
void ShowAllData(const int * arr, int len)
{
int i;
for(i=0; i<len; i++)
printf("%d ", arr[i]);
}
위 함수의 매개변수 선언에서 매개변수 arr을 대상으로 const 선언을 한 이유가 무엇이겠는가? 이 함수를 정의한 사람의 의도를 이야기해 보자.
Q. 아래의 예제는 한 가지 지적할만한 사항을 지니고 있다. 그것이 무엇인지 이야기해 보자. 특히 이와 관련해서 ShowData 함수를 유심히 관찰하기 바란다.
void ShowData(const int * ptr)
{
int * rptr=ptr;
printf("%d \n", *rptr);
*rptr=20;
}
int main(void)
{
int num=10;
int * ptr=#
ShowData(ptr);
return 0;
}