C 기출의 절반이 포인터와 배열이다. 주소를 그림으로 그리고 첨자를 손으로 세면 답이 하나로 좁혀진다
왜 이 장을 하나
C 문제의 함정은 문법이 아니라 지금 포인터가 어디를 가리키는지다. 배열 이름이 주소라는 것, *(p+1) 과 *p+1 의 차이, 2차원 배열의 행 · 열 첨자, 매개변수로 넘어간 배열이 포인터가 되는 것 — 이 넷이 15문항의 전부다. 종이에 칸을 그리며 추적하는 절차를 세운다.
다루는 것포인터 산술 · 배열 첨자 · 2차원 배열 · 주소 전달 · 정렬 코드
문항기출 15 · 예상 3 · 훈련 10
끝나면포인터 식을 보고 칸을 그려 값을 읽는다
01왜 이 장인가
왜 이걸 하나 — 프로그래밍 91문항 중 C 가 42문항이고, 그중 15문항이 포인터 · 배열이다. 11회 중 9회에 나왔다.
11회분 220문항 중 이 장의 기출은 15문항이다. 2023년 2회에는 4문항(순환 출력 · 스택 · 공유 버퍼 · 선택 정렬)이 몰렸고, 2026년 2회 12번(sizeof)까지 이어진다. 코드 추적 훈련 10문항(훈련 C 1~4 · 23~26 · 28 · 29)이 이 장에 붙는다.
꼴
몇 문항
무엇을 적나
보기
문자열 포인터 출력
4
%s · %c 로 여러 줄
2023-1회 2번 · 2023-3회 3번 · 2025-1회 10번 · 2025-3회 2번
→ 답이 여러 줄인 문항이 4개다(2023-1회 2번 5줄 · 2023-3회 3번 5줄 · 2025-1회 10번 2줄 · 2026-2회 12번 4줄). 한 줄이라도 빠지거나 순서가 바뀌면 그 문항이 통째로 나가므로, 줄 수를 먼저 세고 시작한다.
E01 진단의 C 2문항 중 12번(sizeof 와 배열 매개변수)이 이 장이다. 코드 추적은 머릿속으로 하면 첨자 하나가 밀린다 — 칸을 그리고 화살표를 옮기는 습관이 03절이다.
문항 수는 이 노트의 문제 데이터에서 ch=E02 인 것을 센 값이다(2026-09-14). 기출 코드는 grandlife.co.kr 복원에서 옮겼고, 15문항 전부 gcc(도커 alpine)로 실행해 정답을 확인했다. 빈칸 문제 3개는 답을 넣어 실행하거나 컴파일해 확인했다.
02한눈에
왜 이걸 하나 — 시험 전날 규칙 8개를 다시 본다. 전부 「주소냐 값이냐」의 변주다.
배열 이름 = 첫 칸 주소int a[5] 에서 a 는 &a[0]. a[i] 는 *(a + i) 와 같다. 문자열 char w[] = "Art" 는 A · r · t · \0 네 칸.
포인터 산술p + 1 은 한 칸(자료형 크기만큼) 옆의 주소. *(p + 1) 은 그 칸의 값, *p + 1 은 첫 칸 값에 1 을 더한 것. p++ 는 포인터를 옮기고, (*p)++ 는 값을 올린다.
%s 와 %c%s 에 주소를 주면 그 자리부터 \0 전까지 출력. %c 에 값을 주면 글자 하나. %c 에 *p + 4 를 주면 코드가 4 큰 글자(K → O).
2차원 배열a[2][3] 은 행 2 열 3, 메모리에는 한 줄로 1 2 3 4 5 6. a[1][2] = *(*(a + 1) + 2). int *p = a[0] 이면 p[4] 는 5(한 줄로 센다).
함수에 넘기면배열을 넘기면 포인터가 된다 — int arr[] 매개변수의 sizeof(arr) 는 포인터 크기(8). 값을 넘기면 복사본, 주소를 넘기면 원본이 바뀐다. 이중 포인터 int **pp 는 포인터의 주소.
전역 배열 공유같은 전역 버퍼를 돌려주는 함수를 세 번 부르면 세 포인터가 같은 곳을 가리켜 마지막 값이 세 번 찍힌다.
정렬 · 스택 뼈대선택 정렬은 if (a[i] > a[j]) swap 이 오름차순. 버블은 이웃끼리 a[j] > a[j+1]. 스택은 top 을 올리며 넣고 내리며 뺀다. 순환 첨자는 (i + 1) % n.
sizeof배열 자체는 전체 바이트, 포인터는 8(64비트). 원소 수 = sizeof(a) / sizeof(a[0]). 배열 포인터 int (*p)[8] 의 *p 는 배열 전체(32).
03밑바닥
왜 이걸 하나 — 규칙 8개는 메모리를 칸으로 그리면 전부 한 그림에서 나온다. 그림이 있으면 처음 보는 코드도 같은 절차다.
3-1. 배열은 칸의 줄이고 이름은 첫 칸의 번지다
char word[] = "Art"; 는 메모리에 A · r · t · \0 네 칸을 나란히 만들고, word 라는 이름은 그 첫 칸의 주소다. 그래서 printf("%s", word) 는 첫 칸부터 \0 전까지 Art 를 찍고, *word 는 첫 칸의 값 A 다. char *p = word; 로 포인터를 만들어도 같은 칸을 가리키니 *p 도 A 다(2023년 1회 2번).
포인터에 1 을 더하면 한 칸 옆의 주소가 된다. word + 1 은 r 의 주소라 %s 로 찍으면 rt 이고, *(word + 3) 은 넷째 칸 값이다. 2023년 3회 3번은 KOREA 로 이 다섯 가지를 한 문제에 넣었다 — %s word(KOREA), %s word+1(OREA), %c *word(K), %c *(word+3)(E), %c *word+4(K 의 코드 75에 4 를 더한 O).
마지막 것이 가장 자주 틀린다. *(word + 3) 은 「3칸 옆의 값」이고 *word + 3 은 「첫 칸 값에 3 을 더한 것」이다. 괄호가 있으면 주소를 먼저 옮기고, 없으면 값을 먼저 꺼낸다 — * 가 + 보다 먼저이기 때문이다. 2025년 3회 2번도 같은 갈림에서 C 가 답이었다.
3-2. 2차원 배열은 한 줄이다
int a[2][3] = {{1,2,3},{4,5,6}}; 는 그림으로는 2행 3열이지만 메모리에는 1 2 3 4 5 6 이 한 줄로 놓인다. a[1][2] 는 「둘째 행의 셋째 칸」이고 한 줄로 세면 1 × 3 + 2 = 5번째(0부터)라 6 이다. 그래서 int *p = a[0]; 처럼 첫 행의 주소를 한 줄 포인터에 담으면 p[4] 는 5, p[3] 은 4 다(예상 1회 9번).
포인터 식으로 쓰면 *(*(a + 1) + 2) 다. a + 1 은 둘째 행의 주소, *(a + 1) 은 그 행의 첫 칸 주소, 거기에 2 를 더해 셋째 칸, 마지막 * 로 값. 2024년 2회 15번과 훈련 3번이 이 식을 그대로 묻는다. 행 첨자에는 열 개수를 곱한다는 것만 기억하면 어느 칸이든 한 줄 번호로 바꿀 수 있다.
3-3. 함수에 넘기면 배열은 포인터가 된다
매개변수 자리의 int arr[] 는 배열이 아니라 포인터다. 그래서 함수 안에서 sizeof(arr) 는 배열 크기가 아니라 포인터 크기(64비트에서 8)이고, 2026년 2회 12번의 function3 이 8 / 4 = 2 를 찍는다. 배열 전체를 가리키는 int (*arr)[8] 로 받으면 *arr 가 배열 자체라 32 / 4 = 8 이 된다(function4).
같은 문제의 앞부분이 값 전달과 주소 전달이다. function1(&value) 는 주소를 받아 *p = 50 으로 원본을 바꾸고, function2(value) 는 복사본만 60 으로 바꿔 원본은 50 그대로다. 훈련 28번(값 전달 vs 주소 전달)이 같은 원리이고, 2024년 3회 19번은 포인터의 주소(int **)를 넘겨 원본 포인터를 바꾼다.
전역 버퍼도 같은 함정이다. 2023년 2회 12번은 scanf 로 읽어 전역 배열 buffer 의 주소를 돌려주는 함수를 세 번 부른다. 세 포인터가 같은 버퍼를 가리키므로 마지막에 읽은 gamma 가 세 번 찍힌다. 「포인터를 세 개 만들었으니 값도 세 개」라고 생각하면 틀린다.
3-4. 첨자 식과 정렬 뼈대는 손으로 한 바퀴 돌린다
빈칸 문제는 뼈대를 알아야 채운다. 첫 값을 맨 뒤로 보내는 순환 출력은 values[(i + 1) % 5] — i 가 4 일 때 5 % 5 = 0 으로 첫 칸에 돌아온다(2023년 2회 9번, 5 4 3 2 1 을 넣으면 4 3 2 1 5). 선택 정렬의 오름차순은 if (values[i] > values[j]) 에서 바꾸는 것이라 빈칸은 > 다(2023년 2회 14번). 버블 정렬의 swap 은 arr[idx2] = temp 로 끝나고 호출은 bubbleSort(values, size) 다(2023년 1회 14번).
스택은 top 하나로 돌아간다. push 는 top 을 올린 뒤 넣고, pop 은 값을 꺼낸 뒤 top 을 내린다. 2023년 2회 11번은 push 1 · 2, pop → 2, push 3, pop → 3, push 4 · 6, pop → 6, pop → 4, push 5, pop → 5, pop → 1 로 213465 다. pop 이 찍는 것은 가장 최근에 넣은 것이라 순서를 표로 적으면 틀리지 않는다.
통과 기준은 넷이다. 첫째, 문자열 포인터 식 5종(%s p · %s p+1 · %c *p · %c *(p+n) · %c *p+n)의 출력을 KOREA 로 안 보고 적는다. 둘째, 2차원 배열의 칸을 한 줄 번호로 바꾼다. 셋째, 값 전달 · 주소 전달 · 배열 매개변수의 sizeof 를 가른다. 넷째, 스택 · 순환 첨자 · 정렬 뼈대를 손으로 한 바퀴 돌린다. 기출 15문항이 이 넷 안에 있다.
*p + 1 과 *(p + 1) 은 같다.* 가 + 보다 먼저다. *p + 1 은 첫 칸 값에 1 을 더한 것(K → L), *(p + 1) 은 둘째 칸의 값(O). 2023년 3회 3번의 마지막 줄 O 는 *word + 4 라 K 에 4 를 더한 것이다.
함수 안에서도 sizeof(arr) 는 배열 크기다.매개변수 int arr[] 는 포인터라 sizeof 가 8 이다. 2026년 2회 12번의 3.2 가 그 결과다. 배열 크기를 함수 안에서 알려면 길이를 따로 넘기거나 배열 포인터 int (*arr)[8] 로 받는다.
04기출
왜 이걸 하나 — 코드를 종이에 칸으로 그리며 푸는 연습이다. 출력이 여러 줄이면 줄 수를 먼저 센다.
변수마다 칸을 그리고 포인터는 화살표로 그린다. printf 를 만날 때마다 답 칸에 한 줄씩 적고, 정답을 연 뒤 몇째 줄에서 어긋났는지를 보면 규칙 8개 중 무엇이 빠졌는지 나온다.
배열 이름 a와 포인터 p는 같은 곳(문자열 시작 주소)을 가리키는 쪽지입니다. %s는 \0 전까지 전부 출력, *p와 *a는 첫 글자 'A'. for문으로 한 글자씩 출력해도 결국 Art. 복원된 코드를 실행해 위 출력을 그대로 얻었다. (gcc(도커 alpine)) 그랜드라이프 가답안 표기는 「ArtAAArtArt」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
2023-1회 · 14번C
다음 C 프로그램에서 ①과 ②에 들어갈 변수명을 순서대로 쓰시오.
#include <stdio.h>
void swap(int *arr, int idx1, int idx2) {
int temp = arr[idx1];
arr[idx1] = arr[idx2];
arr[①] = temp;
}
void bubbleSort(int *arr, int length) {
for (int i = 0; i < length - 1; i++) {
for (int j = 0; j < length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
swap(arr, j, j + 1);
}
}
}
}
int main(void) {
int values[] = {
85, 75, 50, 100, 95
};
int size = 5;
bubbleSort(values, ②);
return 0;
}
정답① idx2, ② size
swap은 "두 컵의 물을 빈 컵(t) 하나로 맞바꾸기" — t에 A를 붓고, A에 B를 붓고, B에 t를 부으면 끝. 마지막 단계가 ①. 정렬 함수엔 배열과 크기를 전달하므로 ②는 nx. 확인 방법: 컴파일만 확인. (gcc(도커 alpine)) 그랜드라이프 가답안 표기는 「① idx2, ② size」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
2023-2회 · 9번C
정수 다섯 개를 배열에 입력한 뒤 첫 번째 값을 맨 뒤로 보내 출력하려고 한다. ①에 들어갈 식을 쓰시오.
#include <stdio.h>
int main(void) {
int values[5];
int i;
for (i = 0; i < 5; i++) {
scanf("%d", &values[i]);
}
for (i = 0; i < 5; i++) {
printf("%d", values[( ① )]);
}
return 0;
}
정답(i + 1) % 5
%(나머지)는 "회전판". i=0→1번 칸, i=3→4번 칸, i=4→(4+1)%5=0번 칸으로 되돌아옵니다. 원형 큐·순환 구조는 전부 (i+1)%크기 패턴. 빈칸에 답을 넣어 실행하면 출력이 「43215」 로 나오는 것을 확인했다. (gcc(도커 alpine)) 그랜드라이프 가답안 표기는 「(i + 1) % 5」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
2023-2회 · 11번C
다음 C 프로그램의 실행 결과를 쓰시오.
#include <stdio.h>
int stack[10];
int top = -1;
void push(int value) {
stack[++top] = value;
}
int pop(void) {
return stack[top--];
}
int main(void) {
push(5);
push(2);
printf("%d", pop());
push(4);
push(1);
printf("%d", pop());
push(3);
printf("%d", pop());
printf("%d", pop());
push(6);
printf("%d", pop());
printf("%d", pop());
return 0;
}
정답213465
스택은 "접시 쌓기" — 마지막에 올린 접시부터 꺼냅니다(LIFO). 종이에 스택 그림을 그리며 push/pop을 순서대로 추적하는 것이 가장 안전합니다. 복원된 코드를 실행해 위 출력을 그대로 얻었다. (gcc(도커 alpine)) 그랜드라이프 가답안 표기는 「213465」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
2023-2회 · 12번C
다음 C 프로그램에 alpha, beta, gamma를 차례대로 입력했을 때 출력 결과를 줄마다 쓰시오.
세 포인터가 같은 배열(같은 집)을 가리키므로, 마지막 입력 "박영희"가 이전 내용을 덮어씁니다. 쪽지(포인터)가 3장이어도 집이 1채면 내용물은 하나! 복원된 코드를 실행해 위 출력을 그대로 얻었다. (gcc(도커 alpine)) 그랜드라이프 가답안 표기는 「gammagammagamma」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
2023-2회 · 14번C
선택 정렬로 배열을 오름차순 정렬하려고 한다. ①에 들어갈 비교 연산자를 쓰시오.
#include <stdio.h>
int main(void) {
int values[] = {
64, 25, 12, 22, 11
};
int size = sizeof(values) / sizeof(values[0]);
for (int i = 0; i < size - 1; i++) {
for (int j = i + 1; j < size; j++) {
if (values[i] ( ① ) values[j]) {
int temp = values[i];
values[i] = values[j];
values[j] = temp;
}
}
}
return 0;
}
정답>
오름차순 = "앞이 뒤보다 크면 교환". 내림차순이면 <. 정렬 방향과 부등호 방향을 연결해 암기: "오름차순은 큰 놈을 뒤로 보낸다(>)". 확인 방법: > 를 채워 컴파일하고 배열을 찍어 오름차순 11 12 22 25 64 확인. > 를 넣어 컴파일한 뒤 배열을 찍어 보면 11 12 22 25 64 로 오름차순이 된다 (gcc(도커 alpine)) 그랜드라이프 가답안 표기는 「>」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
p+1은 "한 칸 옆에서부터 끝까지"(OREA), *(p+3)은 "3칸 옆 글자"(E), *p+4는 'K'+4 = 문자 코드 연산 = 'O'. 괄호 유무가 완전히 다른 결과 — 최다 함정 포인트! 복원된 코드를 gcc(도커 alpine)로 실행해 위 다섯 줄을 그대로 얻었다. *word + 4 는 문자 코드 K(75)에 4 를 더한 O 다. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
strcpy(text + 3, "de") 는 "abc" 뒤(첨자 3)부터 "de" 를 복사해 "abcde" 가 된다. strlen 은 5, text[4] 는 e 라 e − a = 4, 거기에 1 을 더해 5 + 4 + 1 = 10. 포인터 + 3 은 셋째 칸 뒤에 이어 붙이는 것이고 글자는 코드값이라 뺄 수 있다. 복원된 코드를 gcc(도커 alpine)로 실행해 10 을 얻었다. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
2차원 배열 a에서 *(*(a+i)+j) == a[i][j]. "a+i는 i행으로, +j는 j칸 옆으로" — 겹괄호를 행/열 이동으로 번역하면 쉽습니다. 복원된 코드를 gcc(도커 alpine) 로 실행해 위 출력을 그대로 얻었다. 그랜드라이프 가답안 표기는 「21」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
2024-3회 · 19번C
다음 C 프로그램의 실행 결과를 쓰시오.
#include <stdio.h>
void update(int **values, int size) {
for (int i = 0; i < size; i++) {
*(*values + i) = (*(*values + i) + i) % size;
}
}
int main(void) {
int values[] = {
3, 1, 4, 1, 5
};
int *p = values;
int **pp = &p;
update(pp, 5);
printf("%d", values[2]);
return 0;
}
정답1
이중 포인터 = "쪽지의 위치를 적은 쪽지". **pp는 두 번 찾아가서 값 읽기. 변수→포인터→이중 포인터를 3단 그림으로 그리면 절대 안 틀립니다. 복원된 코드를 gcc(도커 alpine) 로 실행해 위 출력을 그대로 얻었다. 그랜드라이프 가답안 표기는 「1」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
2025-1회 · 10번C
다음 C 프로그램의 실행 결과를 두 줄로 쓰시오.
#include <stdio.h>
int main(void) {
char letters[5] = {
'B', 'A', 'D', 'E', '\0'
};
char target = 'C';
int pos;
printf("%d\n", letters[3] - letters[1]);
for (pos = 0; pos < 4; pos++) {
if (letters[pos] > target)
break;
}
for (int i = 4; i > pos; i--) {
letters[i] = letters[i - 1];
}
letters[pos] = target;
for (int i = 0; i < 5; i++)
printf("%c", letters[i]);
return 0;
}
정답4 BACDE
첫 줄은 letters[3] − letters[1] = E − A = 4(글자는 코드값). 그 뒤 C 를 정렬된 자리에 끼워 넣는다 — B · A · D · E 중 C 보다 큰 첫 글자는 D(pos = 2)이고, 그 뒤를 한 칸씩 밀어 B A C D E. 답은 두 줄이라 4 와 BACDE 를 줄을 나눠 적는다. 복원된 코드를 gcc(도커 alpine)로 실행해 두 줄을 얻었다. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
2025-1회 · 11번C
다음 C 프로그램의 실행 결과를 쓰시오.
#include <stdio.h>
void place(int grid[3][3], const int values[9]) {
for (int i = 0; i < 9; i++) {
grid[((i + 1) / 3) % 3][(i + 1) % 3] = values[i];
}
}
int main(void) {
int grid[3][3];
int values[9] = {
5, 2, 7, 4, 1, 8, 3, 6, 9
};
int total = 0;
place(grid, values);
for (int i = 0; i < 9; i++) {
total += grid[i / 3][i % 3] * (i % 2 == 0 ? 1 : -1);
}
printf("%d", total);
return 0;
}
정답13
malloc = "필요할 때 방 빌리기". 할당 후에는 일반 배열과 똑같이 인덱스·포인터 연산으로 접근합니다. 2025년부터 동적 메모리 유형이 새로 등장 — 개념 1-1, 1-4 참고. 복원된 코드를 gcc(도커 alpine) 로 실행해 위 출력을 그대로 얻었다. 그랜드라이프 가답안 표기는 「13」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
p 는 items[1] 을 가리키므로 offset 2, text "DC". p->text + (2 − 1) 은 둘째 글자의 주소라 %s 로 찍으면 거기서부터 끝까지 C 다. 포인터 + n 은 n 칸 뒤의 주소이고 %s 는 그 자리부터 전까지 찍는다. 복원된 코드를 gcc(도커 alpine)로 실행해 C 를 얻었다. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
2026-1회 · 2번C
다음 C 프로그램의 실행 결과를 쓰시오.
#include <stdio.h>
double arr1(int p[], int len) {
double av = 0;
int i;
for (i = 0; i < len; i++) {
av += (double)p[i];
}
return av / len;
}
double arr2(int *p, int len) {
double av = 0;
int i;
for (i = 0; i < len; i++) {
av += (double)(*(p + i));
}
return av / len;
}
int main(void) {
int arr[10] = {
80, 20, 50, 55, 45, 95, 55, 10, 40, 80
};
int len = 10;
printf("%.2f", arr1(arr, len) + arr2(arr, len));
return 0;
}
정답106.00
arr[i]와 *(arr+i)는 완전히 같으므로 두 함수의 결과도 동일(53+53=106). %.2f는 소수점 둘째 자리까지 — 106.00으로 써야 정답, 106이라고 쓰면 오답! 복원된 코드를 실행해 위 출력을 그대로 얻었다. (gcc(도커 alpine)) 그랜드라이프 가답안 표기는 「106.00」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
2026-2회 · 12번C
다음 C 프로그램의 실행 결과를 줄 단위로 쓰시오. 단, sizeof(int)=4, sizeof(int*)=8이다.
function1 은 주소를 받아 원본을 50 으로 바꾼다. function2 는 값의 복사본만 바꾸므로 원본은 50 그대로. function3 의 int arr[] 는 매개변수 자리에서 포인터로 바뀌므로 sizeof 가 8 → 8/4 = 2. function4 의 *arr 는 int 8개짜리 배열 자체라 32/4 = 8. 앞의 1. 2. 3. 4. 는 프로그램이 찍는 글자다. gcc(64비트, sizeof(int*)=8)로 실행해 4줄을 확인했다. 복원 출처는 grandlife.co.kr 2026-2회 복원 풀이(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·수치가 실제와 다를 수 있다.
p+3은 "3칸 옆부터 끝까지", *(p+1)은 "1칸 옆 글자", *p+1은 'C'+1='D' 코드 연산 — 괄호 위치가 전부입니다.
훈련 C · 2번C포인터 + 건너뛰기 누적
int a[5] = {2, 4, 6, 8, 10};
int *p = a, s = 0;
for (int i = 0; i < 5; i += 2) s += *(p + i);
printf("%d", s);
정답18
i=0,2,4만 방문: 2+6+10=18. *(p+i)는 a[i]와 완전히 동일합니다.
훈련 C · 3번C2차원 배열 이중 역참조
int a[2][3] = {{1,2,3},{4,5,6}};
printf("%d %d", *(*(a+1)+2), a[0][1] + *(a[1]));
정답6 6
*(*(a+1)+2)=a[1][2]=6. *(a[1])은 2행의 첫 원소 4 → 2+4=6. "a+i는 행 이동, +j는 열 이동".
훈련 C · 4번C포인터 swap
void swap(int *x, int *y) { int t = *x; *x = *y; *y = t; }
int main() {
int a = 3, b = 7;
swap(&a, &b);
printf("%d %d", a, b);
}
정답7 3
주소(&)를 넘겼으므로 함수가 원본 집을 직접 바꿉니다. 값만 넘겼다면(swap(a,b)) 3 7 그대로였을 것 — C-28과 비교.
훈련 C · 23번C최솟값·최댓값 동시 탐색
int a[] = {7, 3, 9, 1, 5};
int min = a[0], max = a[0];
for (int i = 1; i < 5; i++) {
if (a[i] < min) min = a[i];
if (a[i] > max) max = a[i];
}
printf("%d %d %d", min, max, max - min);
정답1 9 8
첫 원소를 기준으로 잡고 갱신. min/max 초기값을 0으로 잘못 두는 코드와 비교하는 변형도 출제됩니다.
훈련 C · 24번C버블 정렬 1회전 (중간 상태!)
int a[] = {5, 2, 4, 1, 3};
for (int j = 0; j < 4; j++)
if (a[j] > a[j+1]) { int t = a[j]; a[j] = a[j+1]; a[j+1] = t; }
for (int j = 0; j < 5; j++) printf("%d", a[j]);
정답24135
바깥 루프가 없는 1회전만: 가장 큰 5가 맨 뒤로 밀려남(2,4,1,3,5). 완전 정렬(12345)이라고 쓰면 오답 — 2025 1회에서 실제로 "중간 상태"를 물었습니다.
훈련 C · 25번C선택 정렬 완주
int a[] = {4, 1, 3, 2};
for (int i = 0; i < 3; i++)
for (int j = i + 1; j < 4; j++)
if (a[i] > a[j]) { int t = a[i]; a[i] = a[j]; a[j] = t; }
printf("%d%d%d%d", a[0], a[1], a[2], a[3]);
정답1234
이중 루프가 끝까지 돌면 오름차순 완성. 부등호가 <였다면 내림차순(4321) — 2023 2회 기출 포인트.
훈련 C · 26번C포인터 순회 + 모음 세기
char *p = "informatics";
int c = 0;
while (*p) {
if (*p=='a' || *p=='e' || *p=='i' || *p=='o' || *p=='u') c++;
p++;
}
printf("%d", c);
정답4
i, o, a, i → 4개. while(*p)는 "\0(값 0)을 만나면 거짓" — 문자열 끝 감지의 표준 관용구.
훈련 C · 28번C값 전달 vs 주소 전달
void f(int n) { n = n + 10; }
void g(int *n) { *n = *n + 10; }
int main() {
int a = 5;
f(a); printf("%d ", a);
g(&a); printf("%d", a);
}
정답5 15
f는 "복사본에 낙서"(원본 무변화), g는 "주소로 찾아가 원본 수정". C 함수 문제의 절반이 이 구분입니다.
훈련 C · 29번C인덱스 체인 (연결리스트의 원리)
int data[] = {10, 20, 30, 40};
int next[] = {2, -1, 3, 1};
int cur = 0;
while (cur != -1) {
printf("%d ", data[cur]);
cur = next[cur];
}
정답10 30 40 20
0번(10)→next 2번(30)→3번(40)→1번(20)→-1 종료. "보물찾기 쪽지" — 저장 순서가 아니라 연결 순서대로 출력. 2025년 연결리스트 신유형의 핵심 원리.
직접 돌려 보는 법
이 컴퓨터에는 gcc 가 없어 도커로 돌렸다. 파워셸에서 코드를 main.c 로 저장한 뒤 아래를 치면 컴파일과 실행이 한 번에 된다(도커 데스크톱이 떠 있어야 한다).