반응형

14-1 함수의 인자로 배열 전달하기

함수호출 시 전달되는 인자의 값은 매개변수에 복사되어 들어간다.

int SimpleFunc(int num){....}
int main(void)
{
	int age=17;
    SimpleFunc(age);//age에 저장된 값이 매개변수 num에 복사된다.
}

소스에서 실제로 전달되는 것은 age가 아니라 age에 저장된 값이 복사 되어서 num으로 들어간다. 

int SimpleFunc(int num)
{
   num += 1;
}

복사되어 들어간 값은 SimpleFunc에서 1을 더한다고 해도 변수 age의 값은 증가가 일어나지 않는다.

그럼 이어서 함수호출 시 인자로 배열을 통재로 전달할려면 어떻게 해야 되겠는가?

배열을 통째로 넘겨받으려면 매개변수로 배열을 선언할 수 있어야 한다. 하지만 이것은 허용되지 않는다.

배열을 함수의 인자로 전달하려면

#include <stdio.h>

int SimpleFunc(int* num)
{
    for (int i = 0; i < 3; i++)
        printf("%d ", num[i]);
}
int main()
{
    int arr[3] = { 1,2,3 };
    SimpleFunc(arr);

    return 0;
}

매개변수를 포인터 변수로 선언되어야 한다. SimpleFunc(int *num) {. . . . . }

이를 대신해서 SimpleFunc(int num[]) {. . . . . } 같이 선언 하는것도 가능하다. 

int num[]int *num은 함수의 매개변수에서는 완전히 동일한 선언이다. int num[]이 좀 더 배열을 인자로 전달하는 느낌을 강하게 주기 때문에 int num[] 형태로 더 많이 사용한다.

int num[], int *num은 매개변수에서만 동일한 선언기 때문에 

int *ptr=arr; << int ptr[]=arr;로 대체 할수는 없다.

함수 호출은 매개변수에 주소 값을 전달해야 한다. SimpleFunc(arr);

14-2 Call-by-value vs Call-by-reference

Call-by-value와 Call-by-reference는 함수의 호출 방식을 의미한다.

Call-by-value는 값을 전달하는 형태의 함수 호출이다.

int SimpleFunc(int num){....}
int main(void)
{
	int age=17;
    SimpleFunc(age);//age에 저장된 값이 매개변수 num에 복사된다.
}

위에서 선언한 이런 형식의 함수 호출 방식이 Call-by-value형식이다. 주소 값을 복사해서 함수에 전달하기 때문에 

age변수의 값을 직접적으로 바꾸지는 못한다.

Call-by-reference는 주소 값을 전달하는 형태의 함수 호출이다.

#include <stdio.h>

int SimpleFunc(int* num)
{
    for (int i = 0; i < 3; i++)
         num[i] += 1;
}
int main()
{
    int arr[3] = { 1,2,3 };
    SimpleFunc(arr);
    for (int i = 0; i < 3; i++)
        printf("%d ", arr[i]);
    return 0;
}

 이 소스의 출력결과는 2 3 4 일 것이다. Call-by-reference 호출은 주소 값을 전달받아 주소값에 직접 접근 할 수 있기 때문에 arr 배열에 직접 접근해서 arr 변수의 값을 바꾸는게 가능하다.

14-3 포인터 대상의 const 선언

const 선언은 변수를 변경하지 못하는 상수화하는 목적으로 사용한다. 이러한 const 선언을 포인터 변수에서 사용했을때에 대해 알아보자.

int num= 10;
const int* ptr=&num;
*ptr=20; // 에러
num=20; // 성공

const를 포인터 변수 자료형 앞에 붙이면 포인터 변수가 가리키고 있는 주소의 값을 바꾸는 것을 허용하지 않는다.

int num= 10;
int num2= 20;
int* const ptr=&num;
ptr=&num2; //에러
*ptr=20; // 성공

const가 포인터 변수 자료형 뒤에 있으면 포인터 변수가 가리키는 주소를 바꾸는 것을 허용하지 않는다.

const int* const ptr=&num;

const를 앞 뒤로 다 붙여서 사용할 수도 있다.

 

const가 갖는 의미가 무엇일까?

const가 없으면 컴파일할때 오류가 생기지않고 컴파일 할 것이다. 그렇다면 const 변수를 사용하는 이유는 무엇일까?

int main(void)
{
	const double Pi= 3.141592;
   	 doble rad;
   	 PI = 3.07; // 컴파일 시 오류상황
   	 scanf("%lf", &rad);
   	 printf("circle area %f", rad*rad*PI);
    
   	 return 0;
}

PI를 3.07로 계산한다면 제대로 된 원의 넓이를 계산할 수 없을 것이다. const를 사용하지 않았다면 위와 같은 소스에서 PI를 값이 이상해졌다는 문제점을 파악하지 못할수도 있다. 이 소스는 간단하기 때문에 PI가 다른 수로 변했다는걸 쉽게 확인 할 수 있지만 만약 소스가 100줄만 넘어가도 PI를 다른 값으로 초기화 했다는걸 찾지 못할 것이다. 게다가 최악의 상황은 3.07로 원의 넓이를 계산했다는것 조차 인지하지 못할수도 있다는 것이다. 

그렇기 때문에 고정되는 값에 const를 사용하는 습관을 들여 컴파일에서 잡아주지 못하는 오류를 잡아줄수있다.

 

-윤성우 열혈C프로그래밍을 참고해여 작성한 글입니다.

반응형

+ Recent posts