Company
교육 철학

LV13 포인터의 활용(배열, 함수)

C++ 포인터와 배열 심화 학습

포인터 변수의 활용 (return 값 두개이상 받기)

함수에서 여러 값을 반환하는 방법

일반적으로 함수는 return문을 통해 하나의 값만 반환할 수 있습니다. 하지만 포인터를 활용하면 여러 개의 값을 동시에 반환하는 효과를 얻을 수 있습니다.

기본적인 return문 (값 하나만 반환)

#include <iostream> using namespace std; int Increase(int a) { return a + 1; }
C++
복사

포인터를 이용한 다중 값 변경

#include <iostream> using namespace std; void Increase(int* a, int* b) { *a += 1; // 포인터가 가리키는 원본 변수의 값을 1 증가 *b += 1; // 포인터가 가리키는 원본 변수의 값을 1 증가 } void Insert(int* a, int* b) { *a = 100; // 원본 변수에 100 대입 *b = 100; // 원본 변수에 100 대입 } int main() { int num1 = 10; int num2 = 20; // 값을 1씩 증가시키는 함수 호출 num1 = Increase(num1); // 일반 함수: 반환값을 다시 대입해야 함 num2 = Increase(num2); // 포인터를 이용한 함수 호출: 원본 변수가 직접 변경됨 Increase(&num1, &num2); return 0; }
C++
복사
핵심 개념:
Call by Value: 값을 복사하여 전달, 원본 변수는 변경되지 않음
Call by Reference: 주소를 전달하여 원본 변수를 직접 변경
포인터를 사용하면 함수에서 여러 변수를 동시에 수정할 수 있음

배열을 인자로 함수에 넘기기

배열과 포인터의 관계

배열의 이름은 배열의 첫 번째 원소의 주소를 나타냅니다. 따라서 배열을 함수에 전달할 때는 실제로 포인터가 전달됩니다.
중요한 특징:
배열도 결국 다수의 int 변수의 나열이기 때문에 모든 변수의 주소를 보낼 필요가 없고 시작 주소 하나만 보내면 됩니다
즉, int arr[]의 주소만 보내면 됩니다. 결국 int변수 주소를 보내는 것과 같습니다

1차원 배열을 함수로 전달

#include <iostream> using namespace std; void bbq(int* pArr /*int pArr[10]*/) { *(pArr) = 100; // pArr[0] = 100과 동일 *(pArr + 1) = 100; // pArr[1] = 100과 동일 *(pArr + 2) = 100; // pArr[2] = 100과 동일 *(pArr + 3) = 100; *(pArr + 4) = 100; *(pArr + 5) = 100; *(pArr + 6) = 100; *(pArr + 7) = 100; *(pArr + 8) = 100; *(pArr + 9) = 100; // pArr[9] = 100과 동일 // 배열 표기법도 동일하게 사용 가능 pArr[0] = 200; pArr[1] = 200; pArr[2] = 200; pArr[3] = 200; pArr[4] = 200; pArr[5] = 200; pArr[6] = 200; pArr[7] = 200; pArr[8] = 200; pArr[9] = 200; } int main() { int vect[10] = {}; // 배열의 이름이 배열의 첫번째 원소의 주소와 같다. // 그렇기에 배열을 함수로 전달할 때는 배열의 시작주소이다. bbq(/*&vect[0]*/ vect); return 0; }
C++
복사
포인터 산술 연산 설명:
(pArr + 1): pArr이 가리키는 주소에서 1칸(4바이트) 뒤의 위치
pArr + 1이라고 해서 주소값에 1을 더하는 것이 아니라, 해당 자료형의 데이터 크기만큼 이동
int형은 4바이트이므로 실제로는 주소값에 4가 더해짐

배열 전달의 장점과 특징

포인터 변수를 활용하는 제일 큰 이유는 배열 전체를 복사해서 전달할 것은 너무 큰 일이고 비효율적이어서 배열의 크기만 보내면 8바이트(64bit) 만 복사하면 됩니다.
다만 *(pArr + 1) 이런 방식으로 사용하면 상당히 코드를 작성하는데 불편하다. 그래서 문법상 포인터변수는 배열처럼 바로 사용이 가능하다.
다만 주의해야 할 점이 전달된 배열의 크기를 넘어가지 않게 주의해서 사용해야 한다.
배열에 이름은 해당 배열의 시작 주소이다. 그래서 이름을 전달했을때 넘겨주는시에 복사가 되는것이 아니라 원본이 그대로 넘어간다. (주의해야한다!)

간단한 배열 전체 증가 함수

#include <iostream> using namespace std; void Increase(int pArr[7]) { for (int i = 0; i < 7; i++) { pArr[i]++; } } int main() { int arr[7] = { 123, 42, 2, 66, 7, 9, 10 }; Increase(arr); // 배열의 모든 원소가 1씩 증가 return 0; }
C++
복사
디버거에서 확인할 수 있는 내용:
그래서 조사식에서 배열에 이름을 넣으면 값에 주소가 보여진다.
배열의 주소: 0x000000023c9ffb28 {123, 43, 2, 3, 5, 7, 0} int[7]
각 원소의 값과 타입이 표시됨

2차원 배열을 포인터 변수로 전달해야 할 때의 문법이 약간 다르다

2차원 배열의 메모리 구조 이해

2차원 배열은 메모리상에서는 1차원으로 연속적으로 저장됩니다. 하지만 함수로 전달할 때는 특별한 문법이 필요합니다.
#include <iostream> using namespace std; // 2차원 배열을 매개변수로 받는 방법 1 void kfc2D(int (*pArr2D)[3]/*int pArr2D[3][3]*/) { pArr2D[0][0] = 100; pArr2D[0][1] = 100; pArr2D[0][2] = 100; pArr2D[1][0] = 100; pArr2D[1][1] = 100; pArr2D[1][2] = 100; pArr2D[2][0] = 100; pArr2D[2][1] = 100; pArr2D[2][2] = 100; } // 2차원 배열을 매개변수로 받는 방법 2 void kfc(int* pArr /*int pArr[3]*/) { pArr[0] = 100; pArr[1] = 100; pArr[2] = 100; } int main() { int arr[3][3] = {}; //int** pArr2D = arr; // 틀리다. int(*pArr2D)[3] = arr; // 이렇게 해야한다. // 본질은 1차원배열을 여러번 나누어서 2차원배열을 사용한다. // 그러한 가정 은 이루는 가능성 ( 하나의 함수는 하나의 일만 하도록 만들어야 한다. ) kfc2D(arr); // 각 행을 개별적으로 전달 kfc(arr[0]); // 첫 번째 행 kfc(arr[1]); // 두 번째 행 kfc(arr[2]); // 세 번째 행 return 0; }
C++
복사
2차원 배열 전달 방법:
1.
int (*pArr2D)[3]: 포인터 to 배열 문법 사용
2.
int pArr2D[][3]: 첫 번째 차원은 생략 가능, 두 번째 차원은 반드시 명시
3.
각 행을 개별적으로 1차원 배열로 전달
메모리 구조 설명:
2차원 배열 arr[3][3]는 메모리상에서 9개의 int가 연속으로 배치
arr[0], arr[1], arr[2]는 각각 3개 원소를 가진 1차원 배열의 시작 주소

최대값과 최소값 찾기 (인덱스까지 함께)

값과 위치를 동시에 찾는 알고리즘

단순히 최대값, 최소값만 찾는 것이 아니라 해당 값이 배열의 몇 번째 위치에 있는지도 함께 찾는 방법입니다.
#include <iostream> using namespace std; int main() { int vect[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; int max = INT_MIN; // 가능한 가장 작은 정수값으로 초기화 int min = INT_MAX; // 가능한 가장 큰 정수값으로 초기화 int maxIdx = -1; // 최대값의 인덱스 (초기값은 유효하지 않은 -1) int minIdx = -1; // 최소값의 인덱스 (초기값은 유효하지 않은 -1) for (int i = 0; i < 10; i++) { if (max < vect[i]) { max = vect[i]; // 최대값 갱신 maxIdx = i; // 최대값의 위치 저장 } if (min > vect[i]) { min = vect[i]; // 최소값 갱신 minIdx = i; // 최소값의 위치 저장 } } cout << "최대값: " << max << ", 위치: " << maxIdx << endl; cout << "최소값: " << min << ", 위치: " << minIdx << endl; return 0; }
C++
복사
알고리즘 특징:
INT_MIN, INT_MAX: <climits> 헤더에 정의된 정수의 최소값, 최대값 상수
인덱스 초기화: -1로 초기화하여 유효하지 않은 상태를 나타냄
동시 탐색: 한 번의 반복문으로 최대값과 최소값을 동시에 찾음

2차원 배열에서 최소값과 최대값 위치 기억하기

2차원 배열에서는 행(row)과 열(column) 정보를 모두 저장해야 합니다.
#include <iostream> using namespace std; int main() { int vect[3][3] = { 3, 4, 1, 5, 5, 7, 8, 3, 2, }; int min = 987654321; // 충분히 큰 값으로 초기화 int dy = 0; // 최소값의 행(row) 좌표 int dx = 0; // 최소값의 열(column) 좌표 for (int y = 0; y < 3; y++) { for (int x = 0; x < 3; x++) { if (vect[y][x] < min) { min = vect[y][x]; // 최소값 갱신 dy = y; // 최소값의 행 좌표 저장 dx = x; // 최소값의 열 좌표 저장 } } } cout << "최소값: " << min << endl; cout << "위치: (" << dy << ", " << dx << ")" << endl; cout << "즉, vect[" << dy << "][" << dx << "] = " << min << endl; return 0; }
C++
복사
2차원 배열 탐색의 특징:
이중 반복문: 행과 열을 순차적으로 탐색
좌표 저장: (y, x) 형태로 2차원 위치 정보 저장
실용적 활용: 게임에서 맵의 특정 지점 찾기, 이미지 처리에서 특정 픽셀 찾기 등에 활용
성능 최적화 팁:
최대값과 최소값을 동시에 찾으려면 조건문을 분리하여 각각 검사
배열의 첫 번째 원소로 초기화하면 INT_MIN, INT_MAX보다 안전
동일한 값이 여러 개 있을 때는 첫 번째로 발견된 위치가 저장됨

“강의는 많은데, 내 실력은 왜 그대로일까?”

혼자서 공부하다 보면
이런 생각 들지 않으셨나요?
강의는 다 듣고도 직접 코드는 못 짜겠고,
복습할 땐 어디서부터 다시 시작해야 할지 막막하고,
질문하려 해도 물어볼 사람이 없고,
유튜브 영상도 정답만 보고 따라 치는 느낌
그렇다면 지금이 바로
“나만을 위한 코칭”이 필요한 순간입니다.

당신도 할 수 있습니다.

지금 멤버십을 넘어, 코칭에 도전해보세요.
수많은 수강생들이 얌얌코딩 코칭으로 넥슨, 크래프톤, NC 등 입사에 성공했습니다.
프리미엄 코칭 안내 바로가기
또는 카톡 오픈채팅: 얌얌코딩 상담방
지금도 코딩을 ‘따라 치기만’ 하고 계신가요?
이젠 혼자 설계하고, 스스로 코딩하는 법을 배워야 할 때입니다.
얌얌코딩이 옆에서 함께하겠습니다.