다차원 배열과 포인터 배열

‘혼공 C언어' 14-2강 도전실전예제 문제 (가로 세로의 합 프로그램)

by Younggi Seo

혼공 C언어' 10-2강 도전실전예제 문제(로또 번호

생성 프로그램)



오늘까지 기본기에 해당하는 다차원 배열(14강) 학습을 완료했다.



해당 강좌(다차원배열과 포인터 배열)에서 다룬 소스코드는 아래 필자의 깃헙에서 다운로드할 수 있다.



문제 | 가로 세로의 합 구하기 프로그램
Screenshot 2026-03-23 at 12.13.04.png 가로(6열) 세로(5행) 테이블에서 6열과 5행은 총합이 들어가는 표다.

5행 6열의 2차원 배열을 선언하고 4행 5열 부분은 1부터 20까지 초기화합니다. 초기화된 배열에서 마지막 열의 요소에는 각 행의 합을 저장하고 마지막 행의 요소에는 각 열의 합을 저장한 후 전체 배열의 값을 출력하세요.

가로 세로 행렬값들을 누적시키기 위한 중복 첫 번째 제어문 안과 누적시킨 값(합산 칸)을 출력시키기 위한 두 번째 제어문 안을 어떻게 코딩할까?
생각해야 할 로직(필자의 알고리즘)

sum[4][j] 위치에 합산값 누적시키기

sum[i][5] 위치에 합산값 누적시키기

sum[4][5] 위치의 합산값(1~20) 누적시키기

5개씩 끊어서 출력



대략 위의 로직을 생각해야 하는데, 2차원 배열 특성상 처음부터 for 제어문자(i, j)의 누적을 어떻게 시켜야 하는지에만 난감했다.


살짝 커닝해서, 합산이 되는 위치의 인덱스를 넣은 sum[4][j], sum[i][5]의 합산값을 구하기 위해 반복연산자를 무진장 바꿔가면 결괏값을 확인했다. 2차원 배열이 아니면 아래와 같은 누적연산 대입을

sum += i (sum = sum + i)

sum[4][j] += sum[i][j]; ( sum[4][j] = sum[4][j] + sum[i][j]; )

위와 같이 누적된다는 행렬식을 이해해야 한다. 이 글을 처음 포스팅한 지, 4일이 지난 뒤 다시 코딩할 때도 수많은 삽질 끝에 행과 열의 합산칸에 누적된 값을 구할 수 있었다.



첫 번째, sum[4][j] 위치에 합산값 누적시키기 로직은 해결!

두 번째도, sum[i][5] 위치에 합산값 누적시키기 로직도 동일한 계산식이므로 해결!

sum[i][5] += sum[i][j]; ( sum[i][5] = sum[i][5] + sum[i][j]; )


세 번째 로직도 동일한 연산식 형태이긴 하나, 네 번째부터 진행한 후 가장 귀퉁이에 있는 이 가로세로 총합산값이 0으로 출력되는 것을 확인하고 아래 연산식을 추가함.

sum[i][j] += sum[i][j]; ( sum[i][j] = sum[i][j] + sum[i][j]; )


어디서 줄 바꿈( printf("\n"); )을 해야 하는지 곰곰이 생각해 봤다. 한 행의 열이 6개 출력되고 줄이 바뀌어야 하므로(Carriage Return), 제어문자 j의 반복문이 종료되는 지점(바깥)에 넣어야 했다. 이리하여 다시 주말(3월 22일)에 C와 데이트를 해서 만든 결과!


본인이 직접 완성한 소스 코드 (솔루션)
Screenshot 2026-03-22 at 19.58.39.png



C언어에서 포인터가 꽃이라면, 포인터(포인터 변수가 가리키는 변수의 값)와 배열명(첫 번째 배열 요소를 가리키는 주소 값)은 다르지만, 포인터와 배열은 결국 같다(배열을 논리적으로나 물리적으로나 행렬의 형태로 나타내어 접근이 훨씬 용이하기 때문)는 것을 알아야 하고 다차원 배열을 잘 다루는 것은 비단 수학의 행렬 문제를 잘 푸는데서만 비롯되는 게 아니다. 무엇보다 C언어의 포인터 배열( '혼공 C언어' 15-1장 이중 포인터 활용 2 : 포인터 배열을 매개변수로 받는 함수 파트 )이 왜 쓰이는지부터 알아야 한다.



Screenshot 2026-03-26 at 17.31.24.png 포인터 배열을 매개변수로 받으면, 이중 포인터를 활용해서 값을 건드리지 않고 'Call by Reference' 할 수 있다


포인터 자체는 포인터가 가리키는 변수의 첫 번째 주소 값을 가지는데, 이 포인터도 변수이기 때문에 포인터 자체의 주소 값이 있다. 그래서 이중 포인터를 통해 기존의 포인터 변수의 주소 값을 저장할 수 있는데, 위의 소스 코드처럼 포인터 배열을 매개변수로 받아서 이중포인터를 활용할 수 있다.


배열명 ptr_ary를 인수로 받는 함수의 매개변수(char* 포인터형 *pps 포인터)는 이중 포인터로 선언되었기 때문에, 포인터가 배열명을 저장하면 배열명은 포인터의 주소이므로 [] 대괄호 연산자를 쓴 위의 출력문처럼 각 포인터 배열 요소들의 값을 출력한다.


Screenshot 2026-03-26 at 17.48.00.png 각 포인터 배열 요소들의 값들이 출력하는 위의 소스코드 결괏값




쉽게 말해, 이중 포인터는 포인터를 가리키는 포인터라는 뜻이고, 이중 포인터가 가장 많이 쓰이는 곳은 '포인터 배열'이다. 배열을 선언하고 그 내용물들이 포인터인 경우에, 그 포인터를 수정하려면 이중 포인터를 선언해서 그 포인터 값을 수정한다. 포인터는 직접 주소를 가리킬 수 있기 때문에(역참조), 어셈블리어(컴파일이 컴퓨터가 알아먹는 기계어로 번역하기 전 단계의 코드)와 많이 닮았고, 이 덕분에 각종 메모리 주소를 C에서도 마음대로 접근가능하게 해 준다(히언, 2024).



이번 주 내내 C언어에서의 포인터 배열, 응용포인터, 메모리 동적할당을 빠르게 학습할 것이지만, 결국 원리ㅡ1차원 배열을 모아 2차원 배열처럼 사용 가능한 포인터 배열ㅡ 까지 정확하게 알면 포인터는 단순히 메모리에 직접 접근하기 위한 역할만을 하는 게 아니라는 것을 알 수 있다.




참조

히언. (2024). Embedded Recipe (1st ed.). 스노우북.