C++

[강의] 10월 2일 수업정리

k-codestudy 2024. 10. 3. 15:47

함수에서 배열을 어떻게 사용하는지에 대한 수업을 들었다.

 

#include <iostream>

void func(int arData[3]);

int main()
{
    int arMain[3]{ 3,2,1 };

    func(arMain);
}

void func(int arData[3])
{
    for (int i = 0; i < 3; i++)
    {
        printf("%d ", arData[i]);
    }
    printf("\n");
}

코드 요약 :

이 코드는 arData[3] 배열을 함수 인자로 선언하고, main 함수에서 arMain[3] 배열을 선언하여 func에 전달하여 출력하는 코드이지만 이 코드에는 중요한 문제점이 존재한다.


문제점 :

배열은 함수에 인자로 전달될 때 값의 호출 (call by value) 가 아닌 배열의 첫 번째 요소의 주소가 전달이 되게 된다.

컴퓨터는 배열을 통째로 복사를 하게 되면 과부화가 걸리는 것을 인지하고 있기에 선언한 배열을 만들어주지 않는다.

그렇기에 껍대기는 값의 호출 (call by value) 의 모양을 취하고있지만 실상은 값의 호출 (call by value) 를 하지 않는것이다.

즉, 유일하게 배열만 call by value가 먹히지 않으며, 진짜 배열이 아니라 포인터처럼 동작하게 된다.

 

예시)

#include <iostream>

void func(int arData[3]);

int main()
{
    int arMain[3]{ 3,2,1 };

    func(arMain);
}

void func(int arData[999])
{
    for (int i = 0; i < 3; i++)
    {
        printf("%d ", arData[i]);
    }
    printf("\n");
}

위 코드에서도 함수의 인자 크기 arData[999]는 의미가 없는것이다.

컴파일러에서는 함수인자에 []를 붙히게 되면 배열 인자를 포인터로 해석하게 되므로, 배열 크기는 무시되고 단지 배열의 첫 번째 요소의 주소만 전달하게 되는것이다. ( int *arData로 읽게 되는 것이다.)

 

이유 :

함수 인자에 배열을 사용할 때, 컴파일러는 이를 자동으로 포인터로 변환하여 배열의 시작 주소를 참조하기에 
int arData[3]와 int arData[999]는 동일하게 처리되는것이다.

또한 sizeof를 사용하더라도 포인터의 크기가 나오지 배열의 크기가 나오지 않기 때문에 배열의 크기를 함께 전달해 주는 것이다 중요하다.

 

올바른 코드 작성법:

#include <iostream>

void func(const int *pData, int nLength);

int main()
{
    int arMain[3]{ 3,2,1 };

    func(arMain,3);
}

void func(const int* pData, int nLength)
{
    for (int i = 0; i < nLength; i++)
    {
        printf("%d ", pData[i]);
    }
    printf("\n");
}

 

설명:

  • 포인터와 배열 크기를 함수에 명시적으로 전달해야 한다.
  • nLength는 배열의 크기를 나타내며, 값에 의한 호출 (Call by Value)로 전달된다.
  • 배열의 크기를 전달할 때는 반드시 포인터와 함께 배열 크기를 명시적으로 전달하는 규칙을 따른다.
  • 함수에서 배열을 처리할 때 반드시 배열의 크기를 명확히 해야 한다.
  • 이 규칙을 지킴으로써 혼동을 방지한다.



문제 1. int 형 두개의 수를 함수로 전달하는 큰 수를 받아오는 함수 

#include <iostream>

void maxNumber(int nData1, int nData2, int *nResult);

int main()
{
	int n1{};
	int n2{};
	int nResult{};
	
	scanf_s("%d", &n1);
	scanf_s("%d", &n2);

	maxNumber(n1, n2, &nResult);

	printf("%d\n", nResult);
}

void maxNumber(int nData1, int nData2, int* nResult)
{
	int nMax{};

	if (nData1 > nData2)
		nMax = nData1;
	else
		nMax = nData2;

	*nResult = nMax;
}

 

문제 2. int 형 배열의 총 합을 얻어오는 함수

#include <iostream>

void sumTotal(const int *pData, int nLength, int *nTotal);

int main()
{
	int arData[7]{ 7,6,5,4,3,2,1 };
	int nTotal{};

	sumTotal(arData, 7, &nTotal);

	printf("%d\n", nTotal);
}

void sumTotal(const int* pData, int nLength, int* nSumTotal)
{
	for (int i = 0; i < nLength; i++)
	{
		*nSumTotal += pData[i];
	}
}

 

문제 3. int 형 두개의 숫자를 바꿔주는 함수

#include <iostream>

void exchangeNumber(int nData1, int nData2, int* pData1, int* pData2);

int main()
{
	int n1{};
	int n2{};
	int nResult1{};
	int nResult2{};

	scanf_s("%d", &n1);
	scanf_s("%d", &n2);

	exchangeNumber(n1, n2, &nResult1, &nResult2);

	printf("교환 전 : %d, %d,  교환 후 : %d, %d\n", n1, n2, nResult1, nResult2);
}

void exchangeNumber(int nData1, int nData2, int* pData1, int* pData2)
{
	*pData1 = nData2;
	*pData2 = nData1;
}

 

문제 4. int 형 배열에 특정 숫자를 횟수만큼 입력해주는 함수 ( 0번지부터 순서대로 채워주는 함수 )

#include <iostream>

void printData(int* pData, int nLength, int nNumber, int nFrequency);

int main()
{
	int arData[5]{ 5,4,3,2,1 };
	int nNumber{};
	int nFrequency{};

	scanf("%d", &nNumber);
	scanf("%d", &nFrequency);

	printData(arData, 5, nNumber, nFrequency);

	for (int i = 0; i < 5; i++)
	{
		printf("%d ", arData[i]);
	}
	printf("\n");
}

void printData(int* pData, int nLength, int nNumber, int nFrequency)
{
	if (nFrequency > nLength)
		nFrequency = nLength;

	for (int i = 0; i < nFrequency; i++)
	{
		pData[i] = nNumber;
	}
}

 

 

주의 사항:

  1. 함수 선언 시, 해당 함수가 어떤 의도로 만들어졌는지 명확하게 표현해야 한다. 즉, 사용자의 입장에서 쉽게 이해할 수 있는 코드를 작성하는 것이 중요하다.
  2. 함수에 포인터는 하는 일이 많다. 값을 전달, 값의 내용물을 변경, 배열을 전달, 배열을 바꾸는지 이런 다양한 일을 하지만 포인터는 혼자서 이 모든일을 전부 하지 못하기에 인수를 추가하여 사용해야한다.

 

'C++' 카테고리의 다른 글

[강의] 10월 10일 수업정리  (2) 2024.10.11
[강의] 10월 4일 수업정리  (1) 2024.10.05
[강의] 10월 1일 수업정리  (1) 2024.10.01
[강의] 9월 27일 수업정리  (0) 2024.09.27
[강의] 9월 26일 수업정리  (1) 2024.09.27