좋아! 정보처리기사 실기 시험에서는 기본 문법을 알고 있다고 착각하면 틀리기 쉬운 문제, 즉 "기초 개념 + 트릭(함정)" 문제들이 자주 출제돼. 그래서 다음과 같은 문제를 준비했어:
다음 Java 코드를 실행했을 때 출력 결과를 구하시오.
public class Main {
public static void main(String[] args) {
int[] a = {1, 2, 3};
int[] b = a;
b[0] = 100;
changeArray(a);
System.out.println(a[0]);
}
public static void changeArray(int[] arr) {
arr = new int[]{9, 9, 9};
arr[0] = 500;
}
}
A. 1
B. 100
C. 500
D. 9
int[] a = {1, 2, 3};
→ a는 [1, 2, 3]을 가리킴
→ 그림: a --> [1, 2, 3]
int[] b = a;
→ b도 같은 배열을 참조함
→ 그림: b --> [1, 2, 3] (a와 동일한 객체를 참조)
b[0] = 100;
→ b는 a와 같은 배열을 참조하므로 a[0] = 100이 됨
→ 그림: a --> [100, 2, 3]
changeArray(a); 호출 시:
arr = a 이므로 arr도 a를 참조하게 됨arr = new int[]{9, 9, 9};에서 새로운 배열을 생성하고 참조를 arr이 그것으로 바꿈arr[0] = 500; → 이건 새로 만들어진 [9, 9, 9] → [500, 9, 9]이 되는 것이고, a에는 영향 없음최종적으로 System.out.println(a[0]); 은 a[0] = 100 이므로 100 출력
arr[0] = ... 과 같이 내용을 수정하는 것만 원본 영향을 줌String 은 불변이라 s = "hello"; s.toUpperCase(); 만 하면 변화 없음ArrayList<Integer> a = b; 후 a.add() 하면 b도 영향을 받음int[] arr 과 int arr[] 의 차이는 없음 → 오답 유도 가능성 있음좋아! 그럼 정보처리기사 실기에서 기본 문법과 로직에 숨어 있는 트릭을 노린 문제를 3개 출제하고, 각 문제에 대해 왜 틀리기 쉬운지, 정답은 왜 그게 되는지, 관련 개념은 무엇인지까지 모두 해설해줄게.
다음 코드의 출력 결과는?
public class Main {
public static void main(String[] args) {
int x = 10;
int y = 20;
if (x + y == 10)
System.out.println("A");
if (x + y == 30);
System.out.println("B");
}
}
A. A만 출력
B. B만 출력
C. A, B 둘 다 출력
D. 아무것도 출력 안 됨
if (x + y == 10)
if (x + y == 30); ← 여기 주의!
; 때문에 if문이 "끝나버림"if (조건); 이거는 아무 코드도 실행 안 한다는 뜻임System.out.println("B"); 이건 무조건 실행if (조건); → 세미콜론 때문에 조건과 상관없이 if문 종료됨다음 코드 실행 결과는?
def append_val(val, lst=[]):
lst.append(val)
return lst
print(append_val(1))
print(append_val(2))
print(append_val(3))
A.
[1]
[2]
[3]
B.
[1]
[1, 2]
[1, 2, 3]
C.
[1]
[1, 2]
[3]
D.
[1]
[1]
[1]
lst=[] 는 기본값이 한 번만 만들어짐실제로는 이런 식으로 동작함:
append_val(1) → lst: [] → append(1) → [1]append_val(2) → lst: [1] → append(2) → [1, 2]append_val(3) → lst: [1, 2] → append(3) → [1, 2, 3]다음 C 코드의 출력 결과는?
#include <stdio.h>
typedef struct {
int x;
} Point;
void change(Point p) {
p.x = 999;
}
int main() {
Point a = {100};
change(a);
printf("%d\n", a.x);
return 0;
}
A. 999
B. 0
C. 쓰레기값
D. 100
change(a) 는 값 복사(Call by value) 이기 때문에p는 a의 복사 → p.x = 999 해도 a.x는 영향 없음change(Point *p) 로 포인터 전달해야 함| 개념 | 함정 | 기억할 점 |
|---|---|---|
| Java 조건문 | 세미콜론(;) | if (조건); 은 실행 안 됨 |
| Python 함수 | mutable default | 리스트/딕트는 디폴트값으로 쓰면 안 됨 |
| C 구조체 | 복사 전달 | 원본 수정하려면 포인터 사용해야 함 |
좋아, 그럼 정보처리기사 실기 대비용으로
✅ Java + C + Python
✅ 기초 문법 + 자료구조 + 함수 호출 + 포인터 + 반복문 + 참조 + 예외처리 + 트랩
모든 걸 싹 다 엮은 트랩 문제들을 6문제 출제할게.
각 문제는 반드시 틀리게 유도하는 트릭을 포함하고,
풀이+해설+핵심 개념 정리까지 해준다.
import java.util.*;
public class Main {
public static void main(String[] args) {
List<Integer> a = new ArrayList<>();
a.add(1);
a.add(2);
List<Integer> b = a;
b.add(3);
a = new ArrayList<>();
a.add(100);
System.out.println(b);
}
}
A. [1, 2]
B. [1, 2, 3]
C. [100]
D. [3]
b = a → b는 a와 같은 ArrayList 참조b.add(3) → a도 바뀜: [1, 2, 3]a = new ArrayList<>() → 이제 a는 다른 리스트를 참조함. b는 여전히 예전 리스트System.out.println(b) → [1, 2, 3]a = [[1, 2], [3, 4]]
b = a[:]
b[0][0] = 100
print(a[0][0])
A. 1
B. 100
C. 오류 발생
D. None
b = a[:]는 얕은 복사임. 리스트 객체는 새로 복사하지만, 내부 객체(리스트)는 같은 참조b[0][0] = 100 → a[0][0] = 100도 같이 바뀜#include <stdio.h>
void change(int arr[]) {
arr[0] = 999;
}
int main() {
int a[3] = {1, 2, 3};
change(a);
printf("%d\n", a[0]);
return 0;
}
A. 1
B. 999
C. 쓰레기값
D. 컴파일 오류
arr은 a의 시작 주소 → arr[0] = 999 → a[0]에 바로 반영됨public class Main {
public static void main(String[] args) {
String s = "hello";
s.toUpperCase();
System.out.println(s);
}
}
A. HELLO
B. hello
C. null
D. 컴파일 오류
String은 불변(immutable). s.toUpperCase()는 새 문자열을 리턴하지만 저장 안 했음s는 그대로 "hello"x = 10
def func():
x = x + 1
return x
print(func())
A. 11
B. 10
C. 오류
D. None
x = x + 1 → 함수 내부에서 x를 로컬 변수로 판단x에 값이 없기 때문에 UnboundLocalError 발생global x 선언 필요#include <stdio.h>
typedef struct {
int value;
} Data;
void change(Data *p) {
p->value = 123;
}
int main() {
Data d = {5};
change(&d);
printf("%d\n", d.value);
}
A. 5
B. 123
C. 컴파일 오류
D. 쓰레기값
&d를 넘기므로 p는 d의 주소p->value = 123 → 원본 구조체 d의 값 변경됨| 문제 | 핵심 트릭 | 요점 정리 |
|---|---|---|
| 1 (Java) | 참조 재할당 | a = new는 b에 영향 없음 |
| 2 (Python) | 얕은 복사 | 내부 리스트는 같은 객체 |
| 3 (C) | 배열 포인터 | 배열은 주소 전달됨 |
| 4 (Java) | 불변 객체 | toUpperCase() 결과 저장 안 함 |
| 5 (Python) | 전역 vs 지역 | x = x + 1은 UnboundLocalError |
| 6 (C) | 구조체 포인터 | p->value는 원본 수정 가능 |
좋아! 그럼 이번엔 정보처리기사 실기 스타일로
💣 기본기 부족하면 틀리는 트랩 문제 10개
➡ Java / C / Python / SQL 등 다양한 언어 + 자료형 + 흐름 제어 + 예외 상황 + 참조 트릭 + 로직 꼬기
➡ 객관식 + 틀리게 유도하는 오답 보기 포함
➡ 각 문제에 정답 + 왜 틀리는지 해설 + 핵심 개념 정리 포함
int x = 10;
if (x > 5)
System.out.println("크다");
System.out.println("정말?");
A.
크다
정말?
B.
정말?
C.
크다
D. 아무것도 출력되지 않음
✅ 정답: A
🧠 해설:
중괄호 {} 가 없을 경우, if문은 한 줄만 실행됨.
두 번째 System.out.println("정말?");은 조건문 바깥 코드라 항상 실행됨.
def f(x, lst=[]):
lst.append(x)
return lst
print(f(1))
print(f(2))
A. [1], [2]
B. [1], [1, 2]
C. [1, 2], [2]
D. 오류 발생
✅ 정답: B
🧠 해설:
함수 인자 lst=[] 는 처음 한 번만 생성됨.
그래서 lst가 함수 호출 간에 공유되어 누적됨.
→ mutable default argument 트랩
void update(int *p) {
p = NULL;
}
int main() {
int x = 100;
int *ptr = &x;
update(ptr);
printf("%d\n", *ptr);
}
A. 0
B. 오류
C. 100
D. 쓰레기값
✅ 정답: C
🧠 해설:
p = NULL; 은 복사된 포인터 p만 변경.
ptr 자체는 영향 없음. 여전히 x를 가리킴.
String a = new String("hi");
String b = new String("hi");
System.out.println(a == b);
A. true
B. false
C. 컴파일 오류
D. null
✅ 정답: B
🧠 해설:
new String() 으로 만든 객체는 서로 다른 참조 주소
== 은 주소 비교 → false
내용 비교는 .equals() 를 써야 함
x = 10
def g():
print(x)
x = 20
g()
A. 10
B. 20
C. 오류 발생
D. None
✅ 정답: C (UnboundLocalError)
🧠 해설:
x = 20 이 있기 때문에 x는 지역변수로 간주됨
그런데 print(x)가 그 전에 있어 초기화 안 된 변수 사용 → 오류
다음 중 집계함수를 필터링할 때 사용하는 절은?
A. WHERE
B. GROUP BY
C. HAVING
D. ORDER BY
✅ 정답: C
🧠 해설:
WHERE은 집계되기 전에 필터링
HAVING은 집계 이후 조건 처리
public static void change(int[] arr) {
arr = new int[]{9, 9, 9};
arr[0] = 999;
}
public static void main(String[] args) {
int[] nums = {1, 2, 3};
change(nums);
System.out.println(nums[0]);
}
A. 1
B. 9
C. 999
D. 컴파일 오류
✅ 정답: A
🧠 해설:
arr = new int[]{...} 은 arr 변수만 재할당됨
nums 는 영향 없음 → 원래 값 유지
void set(int arr[]) {
arr[0] = 100;
}
int main() {
int a[3] = {1, 2, 3};
set(a);
printf("%d", a[0]);
}
A. 1
B. 100
C. 오류
D. 0
✅ 정답: B
🧠 해설:
배열은 함수로 넘기면 주소가 전달됨
→ 원본 변경 가능
import copy
a = [[1, 2], [3, 4]]
b = copy.deepcopy(a)
b[0][0] = 999
print(a[0][0])
A. 999
B. 1
C. None
D. 오류
✅ 정답: B
🧠 해설:
deepcopy()는 내부 리스트까지 완전히 복사
→ 원본 a는 영향 없음
SELECT * FROM users WHERE name = NULL;
이 쿼리의 동작 결과는?
A. name이 NULL인 레코드를 찾는다
B. 오류
C. 아무 것도 반환하지 않는다
D. 모든 레코드를 반환한다
✅ 정답: C
🧠 해설:
NULL은 =, != 비교가 안 됨.
IS NULL 써야 찾을 수 있음
→ name = NULL 은 항상 false
| # | 핵심 트랩 | 기억할 점 |
|---|---|---|
| 1 | Java 조건문 줄바꿈 | {} 안 쓰면 한 줄만 |
| 2 | Python 리스트 기본값 | 한 번만 생성됨 |
| 3 | C 포인터 인자 복사 | 원본 안 바뀜 |
| 4 | Java 문자열 비교 | == 말고 .equals() |
| 5 | Python 변수 범위 | 할당하면 지역변수로 판단 |
| 6 | SQL HAVING | 집계 이후 필터링 |
| 7 | Java 배열 재할당 | 참조 변수만 바뀜 |
| 8 | C 배열 함수 전달 | 포인터처럼 전달 |
| 9 | Python deepcopy | 완전 복사 |
| 10 | SQL NULL 비교 | IS NULL 사용해야 함 |
좋은 질문이야!
문제 3번은 이 코드였지:
void update(int *p) {
p = NULL;
}
int main() {
int x = 100;
int *ptr = &x;
update(ptr);
printf("%d\n", *ptr);
}
너의 질문은 이거야:
"포인터는 깊은 복사여서
p = NULL;하면ptr도 바뀌는 거 아냐?"
🤯 하지만 실제로는 반대야!
C에서는 함수 인자로 포인터를 넘겨도 포인터 자체는 값 복사다.
"포인터가 가리키는 대상"은 바꿀 수 있지만,
"포인터 변수 자체"는 함수 안에서 바꿔도 원본 포인터에 영향이 없어.
int *ptr = &x;x의 주소를 가짐 → 예를 들어 ptr = 0x1000, x = 100update(ptr);ptr의 값(=주소 0x1000)을 update() 함수의 p에 복사해서 넘김p는 ptr의 복사본일 뿐그래서 함수 내에서 p = NULL;을 해도,
p 변수의 값을 NULL로 바꾸는 것 (복사본을 변경)ptr에는 아무 영향 없음메인 함수 (main) | update 함수 내부 |
|---|---|
ptr → x (100) | p → 복사본 (same address initially) |
p = NULL → p는 이제 NULL | |
ptr는 그대로 x 가리킴 |
p = NULL; 해도 원본 ptr에는 영향이 없다void update(int *p) {
*p = 999; // 이건 원본 값을 바꾼다!
}
void reassign(int *p) {
int y = 777;
p = &y; // 이건 원본 포인터 ptr은 안 바뀐다!
}
*p = 999; → 원본 변수 x가 999로 바뀜 ✅p = &y; → 원본 포인터는 그대로고, 함수 안에서만 바뀜 ❌📌 요약
*p = ... → 가리키는 대상 변경 → 원본에 영향p = ... → 포인터 변수 자체 변경 → 원본에는 영향 없음