이이프
IeF 제멋대로 세상
이이프
전체 방문자
오늘
어제

공지사항

  • ✔ Info
  • 전체 글보기 (56)
    • 💻프로그래밍 내용 정리 (55)
      • C (0)
      • C++17 (55)
    • 💻게임메이커 (0)
    • 💻언리얼엔진 (0)
    • 💻유니티 (0)
    • 🎈[팀&자작]게임소개 (0)
    • 📃게임제작기술 (0)
    • 🎨그림놀이 (0)
    • 📒대학생활 (0)
    • 😃잡담 (1)
    • 🕹게임성과 (0)
    • 💷자격증 (0)

블로그 메뉴

  • 방명록

최근 글

최근 댓글

티스토리

hELLO · Designed By 정상우.
이이프

IeF 제멋대로 세상

💻프로그래밍 내용 정리/C++17

[C++ 7.2.1] 배열과 포인터

2022. 8. 24. 14:50
728x90

배열과 포인터

배열과 포인터는 서로 비슷하다.

힙에 할당된 배열은 첫 번째 원소를 가리키는 포인터를 참조한다.

스택에 할당된 배열은 배열 문법'[ ]'으로 참조한다.

 

배열 = 포인터

스택 배열에 접근할 때도 포인터를 이용할 수 있다.

배열의 주소는 인덱스가 0인 첫 번째 원소에 대한 주소이다. 컴파일러는 배열의 첫 번째 원소에 대한 주소만 가리킨다.

그래서 힙 배열과 똑같은 방식으로 포인터를 사용할 수 있다.

 

다음 코드는 0으로 초기화한 스택 배열을 만들고 포인터로 접근하는 예이다.

int myIntArray[10];
int* myIntPtr = myIntArray;
// 포인터로 배열 접근하기
myIntptr[4] = 5;

스택 배열을 포인터로 접근하는 기능은 배열을 함수에 넘길 때 특히 유용하다.

 

다음 함수는 정수 배열을 포인터로 받는데 여기서 함수를 호출할 때 배열의 크기를 지정해야 한다.

포인터만으론 크기를 알 수 없기 때문.

void doubleInts(int* theArray, size_t size)
{
    for (size_t i = 0; i < size; i++) {
        theArray[i] *= 2;
    }
}

이 함수를 호출할 때 스택 배열을 전달해도 되고 힙 배열을 전달해도 된다.

힙 배열을 전달하면 이미 포인터가 담겨 있어서 함수에 값으로 전달된다.

스택 배열을 전달하면 배열 변수를 전달하기 때문에 컴파일러가 이를 배열에 대한 포인터로 변환한다.

이때 첫 번째 원소의 주소를 넘겨도 된다.

 

다음은 세 가지 경우를 코드로 표현한 것이다.

size_t arrSize = 4;
int* heapArray = new int[arrSize] {1, 5, 3, 4};
doubleInts(heapArray, arrSize);
delete[] heapArray;

int stackArray[] = { 5,7,9,11 };
arrSize = std::size(stackArray); // C++17부터 <array>를 사용한다.
//arrSize = sizeof(stackArray) / sizeof(stackArray[0]); // C++17 이전 방식: 1장 참조
doubleInts(stackArray, arrSize);
doubleInts(&stackArray[0], arrSize);

배열을 매개변수로 전달하는 과정은 포인터를 매개변수로 전달할 때와 비슷하다.

컴파일러는 배열을 함수로 전ㅋ달하는 부분을 포인터로 취급한다.

배열을 인수로 받아서 그 안에 담긴 값을 변경하는 함수는 복사본이 아닌 원본을 직접 수정한다.

포인터와 마찬가지로 배열을 전달하면 레퍼런스(참조) 전달 방식의 효과가 나타난다.

함수에 전달하는 값이 복사본이 아닌 원본 배열의 주소이기 때문.

 

다음에 나온 doubleInts() 코드는 포인터가 아닌 배열 매개변수를 받더라도 원본 배열이 변경되는 것을 보여준다.

void doubleInts(int theArray[], size_t size)
{
    for (size_t i = 0; i < size; i++) {
        theArray[i] *= 2;
    }
}

 

컴파일러는 이 함수의 프로토타입에서 theArray 뒤에 대괄호([]) 사이에 나온 숫자를 무시한다.

그래서 다음 세 가지 방식으로 변환한 문장은 모두 같다.

void doubleInts(int* theArray, size_t inSize);
void doubleInts(int theArray[], size_t inSize);
void doubleInts(int theArray[2], size_t inSize);

이유는 성능 때문이다.

배열에 담긴 원소를 모두 복사하는 데 시간이 걸릴 뿐만 아니라 메모리 공간도 상당히 차지한다.

항상 포인터를 전달하기 때문에 컴파일러가 배열을 복사하는 코드를 추가할 필요가 없다.

 

길이를 알고 있는 스택 배열을 레퍼런스 전달 방식으로 함수에 전달하는 방법도 있다.

이 방식은 힙 배열에 적용할 수 없다. 다음 코드는 크기가 4인 스택 배열만 인수로 받는다.

void doubleIntsStack(int (&theArray)[4]);

 

함수 템플릿을 사용하면 스택 배열의 크기를 컴파일러가 알아낼 수 있다.

template<size_t N>
void doubleIntsStack(int (&theArray)[N])
{
    for (size_t i = 0; i < N; i++) {
        theArray[i] *= 2;
    }
}

 

배열 문법으로 선언한 배열은 포인터로도 접근할 수 있다.

컴파일러는 함수로 전달하는 배열을 항상 포인터로 취급한다.

'💻프로그래밍 내용 정리 > C++17' 카테고리의 다른 글

[C++ 7.3.1] 포인터 연산  (0) 2022.08.24
[C++ 7.2.2] 포인터와 배열2  (0) 2022.08.24
[C++ 7.1.4] 포인터 다루기  (1) 2022.08.22
[C++ 7.1.3-2] 다차원 배열  (0) 2022.08.22
[C++ 7.1.3-1] 배열, 객체 배열, 배열 삭제  (1) 2022.08.22
    '💻프로그래밍 내용 정리/C++17' 카테고리의 다른 글
    • [C++ 7.3.1] 포인터 연산
    • [C++ 7.2.2] 포인터와 배열2
    • [C++ 7.1.4] 포인터 다루기
    • [C++ 7.1.3-2] 다차원 배열
    이이프
    이이프
    게임 프로그래머 지망생 / Since 2022.08.14

    티스토리툴바