좋아, 아주 좋은 접근이야!
이번엔 다른 언어에서만 나타나는 특징적인 트릭 유형들을 다뤄보자.
특히 C언어와 Python은 Java와는 메모리 처리 방식, 변수 스코프, 포인터/리스트 동작 등에서 큰 차이가 있어서 초보자들이 많이 실수하는 포인트들이 많아.
각 언어당 3문제씩
#include <stdio.h>
int main() {
int a[] = {10, 20, 30};
int *p = a;
*(p + 1) = 99;
printf("%d %d\n", a[1], *(a + 1));
return 0;
}
Q. 출력 결과는?
#include <stdio.h>
void change(int arr[]) {
arr[0] = 100;
}
int main() {
int data[3] = {1, 2, 3};
change(data);
printf("%d\n", data[0]);
return 0;
}
Q. 출력 결과는?
#include <stdio.h>
int x = 1;
void foo() {
int x = 5;
{
int x = 10;
printf("%d ", x);
}
printf("%d ", x);
}
int main() {
foo();
printf("%d\n", x);
return 0;
}
Q. 출력 결과는?
def modify(lst):
lst[0] = 100
data = [1, 2, 3]
modify(data)
print(data)
Q. 출력 결과는?
x = 3
if x > 1:
if x > 5:
print("A")
else:
print("B")
Q. 출력 결과는?
print(5 / 2)
print(5 // 2)
Q. 출력 결과는?
*(p + 1) = 99 → a[1] = 99a[1] = *(a + 1) → 둘 다 99정답:
99 99
정답:
100
int x = 1; // 전역
int x = 5; // foo() 내부
int x = 10; // 블록 안
정답:
10 5 1
정답:
[100, 2, 3]
if x > 5:에 붙음x > 5가 false → else 실행 안 됨정답: (출력 없음)
5 / 2 → 2.5 # 실수 나눗셈
5 // 2 → 2 # 몫만 구하는 나눗셈
정답:
2.5
2
| 언어 | 문제 | 핵심 개념 | 정답 |
|---|---|---|---|
| C | 1 | 배열 = 포인터 | 99 99 |
| C | 2 | 배열 인자 = 주소 전달 | 100 |
| C | 3 | 지역 변수 숨김 | 10 5 1 |
| Python | 1 | 리스트 참조 | [100, 2, 3] |
| Python | 2 | else 위치 | (출력 없음) |
| Python | 3 | 나눗셈 연산 차이 | 2.5, 2 |
->, . 차이)아주 예리한 질문이야.
바로 아래 Python 문제 2를 다시 보자:
x = 3
if x > 1:
if x > 5:
print("A")
else:
print("B")
왜 조건이 안 맞았는데도 "이외의 조건(B)"이 출력되지 않지?
Python에서는 else:는 들여쓰기 기준으로 가장 가까운 if문과 1:1 매칭돼.
그래서 이 코드는 아래처럼 해석되는 거야:
if x > 1:
if x > 5:
print("A")
else:
print("B") # ← 이 else는 x > 5의 실패 시 실행
x = 3x > 1 → ✅ True → 안쪽 if 실행x > 5 → ❌ False → 안쪽 else도 있음print("B") 실행됨!❗ 그런데 너가 말한 코드 출력 안됨이라고 했는데, 사실 이 코드는 "B"가 출력돼야 맞아.
x = 3
if x > 1:
if x > 5:
print("A")
else:
print("B") # ← 이 else는 바깥 if에 붙음
이 경우에는:
x > 1 → ✅ True → 바깥 if가 실행되었으므로 else 무시x > 5 → ❌ → 실행 안됨| 코드 형태 | else의 위치 | 조건 실패 시 출력 |
|---|---|---|
if x > 1: 안쪽에 else 들여쓰기 | 안쪽 if에 붙음 | "B" 출력됨 |
| else를 바깥쪽으로 들여쓰기 | 바깥 if에 붙음 | 아무것도 출력 안됨 |
너가 말한 "아까 Java if-else처럼 이외를 진행 안 하고 불발된다"는 건 맞는 말이야.
Python은 들여쓰기 구조로 if-else 연결을 판단하기 때문에,
else가 바깥쪽에 붙어 있을 경우, 바깥 if 조건이 참이면 else는 아예 무시되고 실행조차 안 돼.
| 언어 | if-else 연결 기준 | 오동작 시 흔한 실수 |
|---|---|---|
| Java | 중괄호 or 가장 가까운 if | else가 어디 붙었는지 헷갈림 |
| Python | 들여쓰기 위치 | 들여쓰기 잘못돼서 실행 안 됨 |
Python에서 복잡한 if-else 쓸 때는 가급적 이렇게 명시해주는 게 좋아:
if x > 1:
if x > 5:
print("A")
else:
print("B") # ← 명확히 안쪽 조건 실패에 대한 else
else:
print("C") # ← 바깥 조건 실패에 대한 처리
좋아, 지금 말한 주제들은 정말 실무 + 시험에서 실수하기 쉬운 고급 트랩이야.
그러면 요청한 C 언어 트랩 3문제 + Python 트랩 3문제, 총 6문제를 트랩 스타일로 아래에 정리해줄게.
#include <stdio.h>
void modify(int **pp) {
**pp = 42;
}
int main() {
int val = 10;
int *p = &val;
modify(&p);
printf("%d\n", val);
return 0;
}
Q. 출력 결과는?
. vs ->)#include <stdio.h>
typedef struct {
int x;
} Data;
int main() {
Data d = {5};
Data *ptr = &d;
ptr->x = 10;
printf("%d %d\n", d.x, (*ptr).x);
return 0;
}
Q. 출력 결과는?
#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr = malloc(sizeof(int) * 3);
arr[0] = 100;
free(arr);
arr[0] = 200; // 문제의 핵심
printf("%d\n", arr[0]);
return 0;
}
Q. 출력 결과는? 프로그램이 반드시 실행될까?
def change(x, y):
x += 1
y[0] += 1
a = 5
b = [5]
change(a, b)
print(a, b[0])
Q. 출력 결과는?
def append_item(val, lst=[]):
lst.append(val)
return lst
print(append_item(1))
print(append_item(2))
Q. 출력 결과는?
nums = [1, 2, 3, 4]
result = map(lambda x: x * 2, nums)
print(result[0])
Q. 출력 결과는?
42int **pp는 이중 포인터modify(&p) → **pp = 42 → *p = 42 → val = 4210 10->는 구조체 포인터가 멤버 접근할 때 사용(*ptr).x == ptr->x → 둘 다 동일 객체 접근200 (또는 쓰레기값, 또는 Segmentation Fault)
free() 후 해당 메모리는 할당 해제되었지만 실제로 접근이 가능할 수도 있음free 이후 접근은 위험하며 보장되지 않는다는 걸 짚는 게 중요!5 6a는 immutable → 함수에서 x += 1 해도 바깥 변수 영향 없음b는 list (mutable) → 내부 값 변경 반영됨[1], [1, 2]lst=[]는 재사용됨 → 값이 계속 누적됨TypeErrorprint(result[0])
map()은 iterator → 인덱스로 접근 ❌list(result)[0]| 번호 | 주제 | 핵심 트릭 설명 | 정답 / 결과 |
|---|---|---|---|
| C4 | 이중 포인터 | **pp = 42 → 원본 변경 | 42 |
| C5 | 구조체 참조 (. vs ->) | ->와 (*p).은 동일 | 10 10 |
| C6 | free 후 접근 | 정의되지 않은 동작 (UB) | 예측 불가 / 위험 경고 |
| Py4 | mutable vs immutable | int는 영향 X, list는 영향 O | 5 6 |
| Py5 | 기본 인자 공유 트랩 | lst=[] 한 번만 생성 | [1], [1, 2] |
| Py6 | map/filter 결과 인덱스 접근 | map은 iterator, 리스트 변환 필요 | TypeError |
| C 트릭 후보 | Python 트릭 후보 |
|---|---|
| 포인터 배열과 배열 포인터 차이 | 변수 aliasing (동일 참조 변수 둘) |
| malloc 누수 + double free 문제 | 제너레이터 vs 리스트 차이 |
| sizeof(struct) 패딩 현상 | 변수 스코프 shadowing |
좋아! 너가 궁금해한 Python 4번과 6번 트랩 문제를 디버깅하듯이 한 줄씩 정확하게 흐름 따라가면서, 왜 이런 결과가 나오는지 완전하게 설명해줄게.
mutable vs immutabledef change(x, y):
x += 1
y[0] += 1
a = 5
b = [5]
change(a, b)
print(a, b[0])
| 자료형 | 예시 | 특징 |
|---|---|---|
| immutable | int, float, str | 함수 안에서 값을 바꿔도 원본에 영향 없음 |
| mutable | list, dict, set | 함수 안에서 변경 시 원본에 영향 있음 |
a = 5a는 정수형(int) → immutable5 저장됨a → 5 (int, immutable)
b = [5]b는 리스트 → mutableb → [5] (list, mutable)
change(a, b)함수에 다음과 같은 인자로 들어감:
x = 5 (a의 복사)y = b (같은 리스트 주소)x += 1x는 정수형 → immutablex = x + 1과 같은 의미a와는 전혀 관계 없음!a는 여전히 5 그대로x: 5 → 6 (새로운 객체 생성)
a는 영향 없음 → 여전히 5
y[0] += 1y = b → 동일한 주소 가리킴y[0] = 5 → += 1 → 6으로 변함b의 내부 값을 변경함y[0]: 5 → 6
→ b[0]도 함께 변경됨
print(a, b[0])a는 int → 변화 없음 → 5b[0]은 리스트 내부 값이므로 함수 안에서 바뀜 → 6# 출력:
5 6
| 항목 | 설명 |
|---|---|
a | int는 immutable, 함수 내 변화 영향 없음 |
b | list는 mutable, 내부 요소 변경 시 반영됨 |
y[0] += 1 | 원본 리스트의 내용이 바뀜 (주소 공유 때문) |
map 객체와 list 변환 누락nums = [1, 2, 3, 4]
result = map(lambda x: x * 2, nums)
print(result[0])
map()은 파이썬 3부터 lazy evaluation을 가진 iteratornums = [1, 2, 3, 4]nums = [1, 2, 3, 4]
map(lambda x: x * 2, nums)map 객체 생성result = map(...) → [2, 4, 6, 8] 이 아님!!
type(result) = <class 'map'>
print(result[0])result는 map 객체 → result[0] 식으로 인덱스 접근 불가
# 이 줄은 에러 발생!
print(result[0])
TypeError: 'map' object is not subscriptable
map 객체는 인덱싱이 안 되므로, list로 변환해서 사용해야 함:
print(list(result)[0]) # → 2
| 항목 | 설명 |
|---|---|
map() | 파이썬 3에서는 lazy iterator 반환 |
result[0] | map 객체는 인덱스 접근 불가 → TypeError |
| 해결 방법 | list(map(...))로 변환 필요 |
| 문제 | 핵심 실수 | 해결 요령 |
|---|---|---|
| 4번 | immutable 객체는 함수 내 변화 영향 없음 | 값 복사됨. 원본은 그대로 유지 |
| 6번 | map 객체는 리스트처럼 인덱스 접근 불가 | list(map(...)) 변환 필요 |