좋아! 정보처리기사 실기에서는 기본 문법 속에 숨어 있는 함정이나 의도적으로 헷갈리게 만든 코드가 자주 출제돼. 그래서 아래와 같이 기초 개념을 묻되, 착각 유도 포인트가 있는 문제를 줄게.
def func(a):
a.append(4)
x = [1, 2, 3]
func(x)
print(x)
[1, 2, 3][1, 2, 3, 4][4]2번 [1, 2, 3, 4]def func(a): # 리스트 a를 받아서
a.append(4) # 여기에 4를 추가한다. 이때 a는 '리스트 객체의 참조'를 받고 있음.
x = [1, 2, 3] # 리스트 객체 생성
func(x) # x가 그대로 func에 전달됨 (얕은 복사, 참조 전달)
print(x) # x는 원본 객체니까, 변경된 상태가 출력됨
a = a + [4] 또는 a = a.copy(); a.append(4)를 했다면 바뀌지 않았을 것.#include <stdio.h>
void change(int arr[]) {
arr[0] = 100;
}
int main() {
int a[3] = {1, 2, 3};
change(a);
printf("%d\n", a[0]);
return 0;
}
11002번 100int arr[]는 결국 함수 내에서 int* arr로 해석된다.arr[0] = 100을 하면 실제 a[0]이 바뀐다.def append_to(val, result=[]):
result.append(val)
return result
print(append_to(1))
print(append_to(2))
[1]
[2]
[1]
[1, 2]
[2]
[2]
2번result=[]는 함수가 처음 정의될 때 한 번만 생성됨.append_to(1) 때 만들어진 리스트가 다음에도 재사용됨.append_to(1) → result = [], append 1 → [1]
append_to(2) → result = [1], append 2 → [1, 2]
def append_to(val, result=None):
if result is None:
result = []
result.append(val)
return result
#include <stdio.h>
int main() {
char c = 255;
printf("%d\n", c);
return 0;
}
255-1에러 발생2번 -1 (대부분 컴파일러에서)char는 기본적으로 signed char 이다. (대부분의 시스템)
char c = 255;는 실제로는 char c = -1; 과 같음
11111111 → signed로 보면 -1그래서 %d로 출력하면 -1
unsigned char c = 255;로 바꾸면 255 출력됨.x = 10
def outer():
x = 20
def inner():
print(x)
inner()
outer()
10202번 20Python의 변수 참조 순서 = LEGB
inner()는 x를 찾을 때, 먼저 자신의 로컬, 그다음 outer()의 x를 찾음
x = 10 (Global)
outer():
x = 20 (Enclosing)
inner():
print(x) ← 여기서 Enclosing 스코프의 x = 20 사용
좋아, 이번엔 "조건문, 반복문, 포인터/주소처리, 변수 스코프, 초기화 순서" 같은 기본 문법을 기반으로 하되, 코드가 직관적으로 보이지만 헷갈리게 설계된 문제들로 내볼게.
Python + C 언어 혼합, 각각 2문제씩 줄게. 이후 원하면 자료구조/알고리즘 함정도 추가 가능해.
a = 5
b = 3
if a < 10:
if b < 5:
print("작다")
else:
print("크다")
print("끝")
a = 5 → a < 10 이므로 첫 번째 if문 실행.b = 3 → b < 5 → 참 → "작다" 출력.❌ 아니다! 잘 봐봐, 정답은 3번이야. 문제를 헷갈리게 설명해봤어!
a = 5 → a < 10 → 실행
b = 3 → b < 5 → 실행 → "작다" 출력
print("끝") → 무조건 실행
▶ 출력:
작다
끝
a = [1, 2, 3, 4]
for x in a:
if x % 2 == 0:
a.remove(x)
print(a)
[1, 3][1, 3, 4][1, 2, 3, 4][1, 3, 4]for x in a: 는 a를 처음에 [1, 2, 3, 4] 상태로 복사된 인덱스로 반복..remove(x)로 리스트 구조가 바뀌면, 반복에서 일부 요소가 건너뛴다.a = [1, 2, 3, 4]
1. x = 1 → 홀수 → 패스
2. x = 2 → 짝수 → remove(2) → a = [1, 3, 4]
3. x = 3 → 그대로
4. x = 4 → 반복 안 됨 (건너뜀)
▶ 최종 결과: [1, 3, 4]
#include <stdio.h>
int main() {
int a[] = {10, 20, 30};
int *p = a;
*(p + 1) = *(p + 2);
printf("%d %d %d\n", a[0], a[1], a[2]);
return 0;
}
10 20 3010 30 3010 20 2010 30 20a[0] = 10
a[1] = 20
a[2] = 30
p = a; // 배열 첫 주소
*(p + 1) = *(p + 2); // a[1] = a[2]
➡ a[1] = 30이 되므로 배열은 [10, 30, 30]
#include <stdio.h>
int main() {
int x = 5;
int y = x + 1;
int x = 3;
printf("%d\n", y);
return 0;
}
64int x = 5;int y = x + 1;int x = 3; → 중복 선언 에러 발생🔴 같은 스코프 안에서는 같은 이름의 변수 x를 두 번 선언할 수 없다!
| 문제 | 주요 함정 포인트 | 정답 |
|---|---|---|
| 1번 | 중첩 if 실행 흐름 | 3번 |
| 2번 | 리스트 반복 중 삭제 | 4번 |
| 3번 | 포인터 인덱스 변경 | 2번 |
| 4번 | 변수 중복 선언 오류 | 3번 |
좋은 질문이야!
문제 2번의 핵심은 바로 for x in a: 반복문과 a.remove(x) 를 같이 쓰면 "일부 요소가 건너뛴다"는 이상한 현상이 생긴다는 거야.
이걸 이해하려면 반복문이 리스트를 어떤 방식으로 순회하는지를 정확히 알아야 해.
a = [1, 2, 3, 4]
for x in a:
if x % 2 == 0:
a.remove(x)
print(a)
a = [1, 2, 3, 4]
for x in a: → 반복문은 a의 인덱스를 0부터 1, 2, 3 차례대로 순회함.
그런데 중간에 a.remove(x)가 실행되면, 리스트 구조 자체가 바뀌면서
그 다음 요소가 한 칸 앞으로 밀리지만, 반복문은 인덱스를 하나씩 증가시켜서 이동하기 때문에
실제로 일부 요소가 건너뛰어짐!
| 반복 | x | 조건(x % 2 == 0) | remove 실행 | 리스트 상태 | 다음 인덱스 | 어떤 일이 일어남 |
|---|---|---|---|---|---|---|
| 1 | 1 | ❌ False | ❌ | [1, 2, 3, 4] | 인덱스 1 | 그대로 진행 |
| 2 | 2 | ✅ True | ✅ | [1, 3, 4] | 인덱스 2 | 3이 인덱스 1 → 건너뜀❗ |
| 3 | 4 | ✅ True | ✅ | [1, 3] | 종료 | 끝 |
for x in a:는 리스트의 인덱스를 기준으로 순회함.
하지만 중간에 a.remove(x)로 요소가 삭제되면,
초기:
인덱스: 0 1 2 3
값: 1 2 3 4
결국 3이 if문에 걸리지 않고 그냥 지나감.
# 안전한 방법
for x in a[:]: # 리스트 복사
if x % 2 == 0:
a.remove(x)
이렇게 하면 for x in a[:]는 원래 리스트의 복사본을 돌기 때문에
중간에 원본 a가 바뀌더라도 반복에는 영향이 없음.
for로 순회할 때 .remove() 같이 구조를 바꾸면 반복 인덱스와 리스트 구조가 어긋난다.list comprehension, filter, while문 등 안전한 방식 사용.