트릭5(마지막 문제 주의)

류한선·2025년 6월 27일

실기연습-2

목록 보기
51/95

좋아, 아주 좋은 접근이야!
이번엔 다른 언어에서만 나타나는 특징적인 트릭 유형들을 다뤄보자.
특히 C언어와 Python은 Java와는 메모리 처리 방식, 변수 스코프, 포인터/리스트 동작 등에서 큰 차이가 있어서 초보자들이 많이 실수하는 포인트들이 많아.


✅ 구성 안내

각 언어당 3문제씩

  • C언어: 포인터, 배열, 스코프, 참조 관계
  • Python: 리스트 참조, 조건문 트릭, 자료형 구분

🧪 C 언어 트랩 문제


✅ [C 문제 1] 포인터와 배열

#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. 출력 결과는?


✅ [C 문제 2] 함수 인자 배열 전달

#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. 출력 결과는?


✅ [C 문제 3] 지역 변수와 스코프

#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. 출력 결과는?


🐍 Python 트랩 문제


✅ [Python 문제 1] 리스트 참조 트랩

def modify(lst):
    lst[0] = 100

data = [1, 2, 3]
modify(data)
print(data)

Q. 출력 결과는?


✅ [Python 문제 2] 조건문 줄 배치 트랩

x = 3

if x > 1:
    if x > 5:
        print("A")
else:
    print("B")

Q. 출력 결과는?


✅ [Python 문제 3] 정수 나눗셈 vs 실수 나눗셈

print(5 / 2)
print(5 // 2)

Q. 출력 결과는?


✅ 정답 및 해설


🔹 C 문제 1

  • *(p + 1) = 99a[1] = 99
  • a[1] = *(a + 1) → 둘 다 99

정답:

99 99

🔹 C 문제 2

  • 배열은 포인터로 전달 → 함수 안에서 변경 시 외부 배열도 바뀜

정답:

100

🔹 C 문제 3

int x = 1;           // 전역
int x = 5;           // foo() 내부
int x = 10;          // 블록 안

정답:

10 5 1

🔹 Python 문제 1

  • 리스트는 참조형 → 함수에서 값 바꾸면 원본도 바뀜

정답:

[100, 2, 3]

🔹 Python 문제 2

  • else는 바로 앞의 if x > 5:에 붙음
    x > 5가 false → else 실행 안 됨

정답: (출력 없음)


🔹 Python 문제 3

5 / 22.5     # 실수 나눗셈
5 // 22       # 몫만 구하는 나눗셈

정답:

2.5  
2

🔄 정리 요약표

언어문제핵심 개념정답
C1배열 = 포인터99 99
C2배열 인자 = 주소 전달100
C3지역 변수 숨김10 5 1
Python1리스트 참조[100, 2, 3]
Python2else 위치(출력 없음)
Python3나눗셈 연산 차이2.5, 2

🧠 다음 추천 연습 방향

C 트랩 주제 추가 가능:

  • 포인터 이중참조
  • 구조체 참조 (->, . 차이)
  • 메모리 누수 / free 사용

Python 트랩 주제 추가 가능:

  • mutable vs immutable
  • 함수 default 인자 참조 공유
  • range, map, filter 함수 오작동

아주 예리한 질문이야.
바로 아래 Python 문제 2를 다시 보자:

x = 3

if x > 1:
    if x > 5:
        print("A")
else:
    print("B")

❓ 질문 요지

왜 조건이 안 맞았는데도 "이외의 조건(B)"이 출력되지 않지?


📌 핵심 원인: else는 항상 "바로 앞 if"에 붙는다

Python에서는 else:는 들여쓰기 기준으로 가장 가까운 if문1:1 매칭돼.

그래서 이 코드는 아래처럼 해석되는 거야:

if x > 1:
    if x > 5:
        print("A")
    else:
        print("B")  # ← 이 else는 x > 5의 실패 시 실행

🔎 현재 상황 흐름 정리:

  • x = 3
  • x > 1 → ✅ True → 안쪽 if 실행
  • x > 5 → ❌ False → 안쪽 else도 있음
    print("B") 실행됨!

❗ 그런데 너가 말한 코드 출력 안됨이라고 했는데, 사실 이 코드는 "B"가 출력돼야 맞아.

🤔 혹시 아래처럼 else의 들여쓰기 위치를 잘못 쓴 버전을 의미한 걸까?

x = 3

if x > 1:
    if x > 5:
        print("A")
else:
    print("B")  # ← 이 else는 바깥 if에 붙음

이 경우에는:

  • x > 1 → ✅ True → 바깥 if가 실행되었으므로 else 무시
  • 안쪽 x > 5 → ❌ → 실행 안됨
  • 그런데 else는 바깥 if의 else이므로 실행되지 않음

▶ 출력 결과: 아무것도 출력되지 않음 (불발)


✅ 정리하면

코드 형태else의 위치조건 실패 시 출력
if x > 1: 안쪽에 else 들여쓰기안쪽 if에 붙음"B" 출력됨
else를 바깥쪽으로 들여쓰기바깥 if에 붙음아무것도 출력 안됨

💬 결론

너가 말한 "아까 Java if-else처럼 이외를 진행 안 하고 불발된다"는 건 맞는 말이야.
Python은 들여쓰기 구조로 if-else 연결을 판단하기 때문에,
else가 바깥쪽에 붙어 있을 경우, 바깥 if 조건이 참이면 else는 아예 무시되고 실행조차 안 돼.


📘 Java와 비교 요약

언어if-else 연결 기준오동작 시 흔한 실수
Java중괄호 or 가장 가까운 ifelse가 어디 붙었는지 헷갈림
Python들여쓰기 위치들여쓰기 잘못돼서 실행 안 됨

✅ 추가 팁

Python에서 복잡한 if-else 쓸 때는 가급적 이렇게 명시해주는 게 좋아:

if x > 1:
    if x > 5:
        print("A")
    else:
        print("B")  # ← 명확히 안쪽 조건 실패에 대한 else
else:
    print("C")  # ← 바깥 조건 실패에 대한 처리

좋아, 지금 말한 주제들은 정말 실무 + 시험에서 실수하기 쉬운 고급 트랩이야.
그러면 요청한 C 언어 트랩 3문제 + Python 트랩 3문제, 총 6문제를 트랩 스타일로 아래에 정리해줄게.


🧪 C 언어 트랩 문제 (고급 트릭)


✅ [C 문제 4] 포인터 이중참조 (double pointer)

#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. 출력 결과는?


✅ [C 문제 5] 구조체 참조 연산자 차이 (. 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. 출력 결과는?


✅ [C 문제 6] free() 후 메모리 접근

#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. 출력 결과는? 프로그램이 반드시 실행될까?


🐍 Python 트랩 문제 (고급 트릭)


✅ [Python 문제 4] mutable vs immutable 객체 변경

def change(x, y):
    x += 1
    y[0] += 1

a = 5
b = [5]
change(a, b)
print(a, b[0])

Q. 출력 결과는?


✅ [Python 문제 5] 함수의 기본 인자 공유 트랩

def append_item(val, lst=[]):
    lst.append(val)
    return lst

print(append_item(1))
print(append_item(2))

Q. 출력 결과는?


✅ [Python 문제 6] map / filter + list 변환 누락

nums = [1, 2, 3, 4]
result = map(lambda x: x * 2, nums)
print(result[0])

Q. 출력 결과는?


🧠 정답 및 해설


✅ C 문제 4: 정답: 42

  • int **pp는 이중 포인터
  • modify(&p)**pp = 42*p = 42val = 42

✅ C 문제 5: 정답: 10 10

  • ->는 구조체 포인터가 멤버 접근할 때 사용
  • (*ptr).x == ptr->x → 둘 다 동일 객체 접근

✅ C 문제 6: 정답: 예측 불가, 하지만 대부분은

200 (또는 쓰레기값, 또는 Segmentation Fault)
  • free() 후 해당 메모리는 할당 해제되었지만 실제로 접근이 가능할 수도 있음
  • 정의되지 않은 동작 → "UB (Undefined Behavior)"
  • 시험에서는 free 이후 접근은 위험하며 보장되지 않는다는 걸 짚는 게 중요!

✅ Python 문제 4: 정답: 5 6

  • a는 immutable → 함수에서 x += 1 해도 바깥 변수 영향 없음
  • b는 list (mutable) → 내부 값 변경 반영됨

✅ Python 문제 5: 정답: [1], [1, 2]

  • 함수의 default 인자인 리스트는 한 번만 생성됨
  • lst=[]는 재사용됨 → 값이 계속 누적됨
    (시험 트랩 단골!)

✅ Python 문제 6: 정답: TypeError

print(result[0])
  • map()은 iterator → 인덱스로 접근 ❌
  • 해결: list(result)[0]

✅ 요약 정리표

번호주제핵심 트릭 설명정답 / 결과
C4이중 포인터**pp = 42 → 원본 변경42
C5구조체 참조 (. vs ->)->(*p).은 동일10 10
C6free 후 접근정의되지 않은 동작 (UB)예측 불가 / 위험 경고
Py4mutable vs immutableint는 영향 X, list는 영향 O5 6
Py5기본 인자 공유 트랩lst=[] 한 번만 생성[1], [1, 2]
Py6map/filter 결과 인덱스 접근map은 iterator, 리스트 변환 필요TypeError

🔁 추천 추가 학습 주제

C 트릭 후보Python 트릭 후보
포인터 배열과 배열 포인터 차이변수 aliasing (동일 참조 변수 둘)
malloc 누수 + double free 문제제너레이터 vs 리스트 차이
sizeof(struct) 패딩 현상변수 스코프 shadowing

좋아! 너가 궁금해한 Python 4번과 6번 트랩 문제를 디버깅하듯이 한 줄씩 정확하게 흐름 따라가면서, 왜 이런 결과가 나오는지 완전하게 설명해줄게.


✅ Python 트랩 문제 4: mutable vs immutable

🔢 문제 코드 다시 보기:

def change(x, y):
    x += 1
    y[0] += 1

a = 5
b = [5]
change(a, b)
print(a, b[0])

📌 먼저 개념 차이 요약:

자료형예시특징
immutableint, float, str함수 안에서 값을 바꿔도 원본에 영향 없음
mutablelist, dict, set함수 안에서 변경 시 원본에 영향 있음

🔍 한 줄씩 디버깅 해보자

🔹 a = 5

  • a는 정수형(int) → immutable
  • 메모리 어딘가에 값 5 저장됨
a → 5 (int, immutable)

🔹 b = [5]

  • b는 리스트 → mutable
  • 리스트 안에 값 5가 들어 있음
b → [5] (list, mutable)

🔹 change(a, b)

함수에 다음과 같은 인자로 들어감:

  • x = 5 (a의 복사)
  • y = b (같은 리스트 주소)

🔸 x += 1

  • x는 정수형 → immutable
  • x = x + 1과 같은 의미
  • x가 새로 6이 됨
  • 그런데 이건 a와는 전혀 관계 없음!
  • a는 여전히 5 그대로
x: 5 → 6 (새로운 객체 생성)
a는 영향 없음 → 여전히 5

🔸 y[0] += 1

  • 리스트 y = b → 동일한 주소 가리킴
  • y[0] = 5+= 16으로 변함
  • 이건 원본 리스트 b의 내부 값을 변경함
y[0]: 5 → 6
→ b[0]도 함께 변경됨

🔹 최종 출력: print(a, b[0])

  • a는 int → 변화 없음5
  • b[0]은 리스트 내부 값이므로 함수 안에서 바뀜6
# 출력:
5 6

✅ 결론 요약:

항목설명
aint는 immutable, 함수 내 변화 영향 없음
blist는 mutable, 내부 요소 변경 시 반영됨
y[0] += 1원본 리스트의 내용이 바뀜 (주소 공유 때문)

✅ Python 트랩 문제 6: map 객체와 list 변환 누락

🔢 문제 코드 다시 보기:

nums = [1, 2, 3, 4]
result = map(lambda x: x * 2, nums)
print(result[0])

📌 핵심 포인트

  • map()파이썬 3부터 lazy evaluation을 가진 iterator
  • 즉, 리스트처럼 인덱스로 바로 접근할 수 없다

🔍 코드 디버깅

🔹 nums = [1, 2, 3, 4]

  • 정수 4개가 들어 있는 리스트
nums = [1, 2, 3, 4]

🔹 map(lambda x: x * 2, nums)

  • 각 요소에 대해 x * 2를 적용하는 map 객체 생성
  • 하지만 이건 아직 계산되지 않은 iterator
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(...)) 변환 필요

0개의 댓글