포인터와 함수에 대한 이해

유석현(SeokHyun Yu)·2022년 7월 18일

C

목록 보기
15/26
post-thumbnail

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

void Func1(int* arr)
{
   sizeof(arr); //포인터 변수 arr의 크기 반환
}

void Func2(int* arr, int num) //main함수에서 arr의 크기를 받음
{
}

int main(void)
{
   int arr[3]={1,2,3};
   Func1(arr);
   Func2(arr, sizeof(arr)/sizeof(int));

   return 0;
}
"배열의 주소 값을 인자로 전달받는 매개변수는 포인터 변수이기 때문에 이를 대상으로 sizeof 연산을 할 경우,

배열의 크기가 반환되지 않고 포인터 변수의 크기가 반환된다."
"이렇듯 함수 내에서는 인자로 전달된 배열의 길이를 계산할 수가 없기 때문에,

배열의 크기나 길이정보도 함께 인자로 전달해야 한다."

2. Call-by-value vs Call-by-reference

함수를 호출할 때 단순히 을 전달하는 형태의 함수호출을 가리켜 Call-by-value라 하고, 메모리의 접근에 사용되는 주소 값을 전달하는 형태의 함수호출을 가리켜 Call-by-referenc라 한다.


3. scanf 함수호출 시 &연산자를 붙이는 이유

int main(void)
{
    int nun;
    scanf("%d", &num);
    ...
}

위의 scanf함수호출이 완료되면 변수 num에는 값이 채워진다.

즉 프로그램 사용자로부터 값을 입력 받아서 변수 num에 그 값을 채우는 일을 scanf함수가 하는 것이다.

그리고 이를 위해서 scanf함수는 변수 num의 주소 값을 알아야 한다.

그래야 변수 num에 접근을 해서 값을 채워 넣을 수 있기 때문이다.

그래서 scanf함수호출 시에 변수 num의 주소 값을 전달하고 있다.

이제 변수 num의 앞에 &연산자를 붙이는 이유를 알겠는가?

이렇듯 scanf함수의 호출도 Call-by-reference형태의 함수호출에 해당한다.

그렇다면 문자열을 입력 받을 때에는 왜 & 연산자를 붙여주지 않았던 것일까?

이와 관련해서 다음 코드를 보자.

int main(void)
{
    char str[30];
    scanf("%s", str);
    ...
}

이전에도 보였듯이 문자열은 위와 같은 방식으로 입력 받는다.

그리고 문자열이 저장될 배열의 이름 str의 앞에는 &연산자를 붙이지 않는다.

str은 그 자체로 배열의 주소 값이기 때문이다!

그냥 str을 전달하면 배열의 주소 값이 전달되지 않는가!

따라서 & 연산자를 붙일 이유가 없는 것이다.


4. 포인터 대상의 const 선언

int num1=20;
int num2=30;

const int* ptr1 = &num1;
*ptr1=20 //불가능

int* const ptr2 = &num1;
ptr2=&num2

첫 번째 const선언은 포인터 변수 ptr1을 이용해서 ptr1이 가리키는 변수에 저장된 값을 변경하는 것을 허용하지 않는다는 뜻이다.

두 번째 const선언은 포인터 변수 ptr2상수로 만들어 한 번 주소 값이 저장되면 그 값의 변경이 불가능하게 된다.(포인터 상수)

profile
Backend Engineer

0개의 댓글