값 전달2

류한선·2025년 6월 28일

실기연습-2

목록 보기
54/95

정말 좋은 질문이에요!
**"for문 안에 변수 선언 vs 밖에서 선언"**의 차이는
결국 **그 변수의 ‘수명(lifetime)’과 ‘저장된 값의 지속성’**에 영향을 줍니다.

지금 바로 아래처럼, 비교 예제 2개를 통해
값이 왜 다르게 나오는지 디버깅하듯이 완전 상세하게 설명드릴게요.


✅ 예제 1: for문 안에서 변수 선언 — 매번 새로 만들어짐

#include <stdio.h>

int main() {
    int sum = 0;

    for (int i = 0; i < 3; i++) {
        int temp = 0;       // 🔴 매 반복마다 '새로운 temp' 변수가 생성됨
        temp += i;          // temp = 0 + i;
        sum += temp;        // sum에 지금 temp를 더함
    }

    printf("sum = %d\n", sum);
    return 0;
}

🔍 흐름 따라가기

반복 itemp 생성 위치temp 값 계산sum 누적
0temp = 0temp += 0 → 0sum = 0
1temp = 0temp += 1 → 1sum = 1
2temp = 0temp += 2 → 2sum = 3
// 각 반복마다 temp = 0 으로 새로 만들어짐

👉 sum = 3이 최종 결과


✅ 예제 2: for문 밖에서 변수 선언 — temp 값이 누적됨

#include <stdio.h>

int main() {
    int sum = 0;
    int temp = 0;       // 🟢 한번만 선언되고, 값이 누적됨

    for (int i = 0; i < 3; i++) {
        temp += i;      // 이전 temp 값에 계속 i를 더함
        sum += temp;
    }

    printf("sum = %d\n", sum);
    return 0;
}

🔍 흐름 따라가기

반복 itemp 누적 방식sum 누적
0temp = 0 + 0 = 0sum = 0
1temp = 0 + 1 = 1sum = 1
2temp = 1 + 2 = 3sum = 1 + 3 = 4

👉 sum = 4이 최종 결과


✅ 차이를 시각화해보자!

[for문 안에 temp 있을 때]
i=0  temp=0  sum=0
i=1  temp=0→1  sum=0+1=1
i=2  temp=0→2  sum=1+2=3

[for문 밖에 temp 있을 때]
i=0  temp=0+0=0  sum=0
i=1  temp=0+1=1  sum=0+1=1
i=2  temp=1+2=3  sum=1+3=4

✅ 요약 정리

선언 위치효과sum 값
for문 안temp가 매 반복마다 새로 만들어짐3
for문 밖temp 값이 반복하며 누적됨4

🧠 이유를 한 문장으로 설명하면?

"for문 안에서 선언된 변수는 반복할 때마다 새로 만들어진다.
밖에서 선언하면 이전 값이 남아 있다."


🚨 덧붙임: 이건 단순히 ‘값이 영향 받느냐’가 아니라

**"변수가 사라지는 타이밍"**과 **"이전 값을 기억하느냐"**의 문제예요.

  • int temp = 0;이 for문 에 있으면 매번 새로 생성 → 이전 값 유지 ❌
  • int temp = 0;에 있으면 한 번만 생성 → 이전 값 계속 사용됨 ✅

🤔 이해 확인을 위한 퀴즈

아래 코드의 출력은 무엇일까요?

#include <stdio.h>

int main() {
    for (int i = 0; i < 3; i++) {
        int x = 0;
        x++;
        printf("x = %d\n", x);
    }
    return 0;
}

좋습니다!
지금 우리가 볼 코드는 반복문 안에서 변수 x가 어떻게 작동하는지,
초기화 위치에 따라 값이 매번 리셋되는지 유지되는지를 확인하는 좋은 예제예요.


🔍 문제 다시 보기:

#include <stdio.h>

int main() {
    for (int i = 0; i < 3; i++) {
        int x = 0;
        x++;
        printf("x = %d\n", x);
    }
    return 0;
}

✅ 한 줄씩 해부하면서 흐름 따라가기:

🔸 1. int main() 시작

  • main 함수 시작
  • for (int i = 0; i < 3; i++) → i는 0부터 2까지 반복됨 (총 3번)

🔄 첫 번째 반복 (i = 0)

int x = 0;
x++;
printf("x = %d\n", x);
  • x = 0; → 새로운 지역 변수 x가 만들어지고 0으로 초기화됨
  • x++; → x = 0 + 1 → x는 1이 됨
  • 출력 → x = 1

이때 이 x는 이 블록(for문 한 사이클)이 끝나면 사라짐!


🔄 두 번째 반복 (i = 1)

  • 또다시 int x = 0;새로운 x가 만들어짐, 이전 x와 완전 다른 메모리
  • x++ → x는 0 → 1
  • 출력 → x = 1

🔄 세 번째 반복 (i = 2)

  • 다시 int x = 0; → 새 x
  • x++ → x는 1
  • 출력 → x = 1

✅ 최종 출력 결과

x = 1
x = 1
x = 1

🧠 핵심 요약:

선언 위치효과값 유지 여부
for문 안매번 새 변수 생성 → 초기화됨❌ 유지 안 됨
for문 밖한 번 생성된 변수 사용 → 누적됨✅ 유지됨

🔁 만약 x를 for문 밖에 선언했다면?

#include <stdio.h>

int main() {
    int x = 0;
    for (int i = 0; i < 3; i++) {
        x++;
        printf("x = %d\n", x);
    }
    return 0;
}

👉 결과:

x = 1
x = 2
x = 3

이유: x가 한 번만 만들어지고, x++으로 계속 누적되니까!


✅ 결론 한 줄 요약:

반복문 안에서 변수를 선언하면 매번 새로 만들어지므로, 값이 유지되지 않는다!


맞아요! 아주 핵심을 잘 짚으셨어요 👏
이제 그 내용을 완전하게 정리해드릴게요.
지금 궁금하신 건 바로 함수에 값을 전달할 때 원본이 바뀌느냐?
“값 전달 vs 참조 전달” 개념입니다.


✅ 정리: int는 값 전달, 배열은 참조 전달

📌 C 언어에서 함수에 인자를 넘길 때:

자료형전달 방식원본 값이 바뀌는가?
int, char 등 기본형값 전달 (Call by Value)❌ 아니요 (복사본만 수정됨)
int[], 포인터 등참조 전달처럼 동작 (주소 전달)✅ 예, 원본 값이 바뀜

✅ 왜 기본형(int)은 값이 안 바뀌나?

void change(int x) {
    x = 100;
}

int main() {
    int a = 10;
    change(a);
    printf("a = %d\n", a); // 🔸 출력: 10
}
  • change(a)a복사본 x를 만든 것
  • x는 지역 변수이므로 x를 바꿔도 a와는 아무 관련 없음

✅ 반면 배열은 왜 바뀌는가?

void change(int arr[]) {
    arr[0] = 100;
}

int main() {
    int a[3] = {1, 2, 3};
    change(a);
    printf("a[0] = %d\n", a[0]); // 🔸 출력: 100
}
  • 배열 a는 함수에 넘길 때 주소로 전달됨
  • 즉, arr[0] = 100은 곧 a[0] = 100과 같음
  • 함수 안에서 원본 배열을 직접 건드리는 것이라 바뀜

✅ 포인터도 마찬가지

void change(int* p) {
    *p = 100;
}

int main() {
    int a = 10;
    change(&a);
    printf("a = %d\n", a); // 🔸 출력: 100
}
  • &a는 a의 주소
  • p는 그 주소를 받아서 *p = 100; → a에 직접 대입

✅ 도식으로 표현하면:

[ int x = 10 ] → 값 복사 → x = 10 (함수 안에서만 사용됨)

[ int arr[] = {1, 2, 3} ] → 주소 전달 → arr[0] = 원본에 직접 영향

[ int *p = &a ] → 주소 전달 → *p = a 직접 바꿈

💡 기억법:

✔️ 기본형은 복사해서 전달 → 원본 영향 ❌
✔️ 배열, 포인터는 주소를 전달 → 원본 영향 ✅


🧠 덧붙임: C에는 참조 전달이 없다?

C 언어는 엄밀히 말하면 참조(reference) 전달 문법이 없고,
모든 건 값으로 전달되는데,
배열과 포인터는 주소 자체가 값이기 때문에 원본에 영향을 줄 수 있는 것입니다.


🧪 요약

인자 타입전달되는 것원본 변경됨?예시 함수
int a값 (복사본)void f(int x)
int a[]주소void f(int arr[])
int* p주소void f(int* p)

정말 날카로운 질문이에요! 👏
지금 궁금하신 부분은:

change(&a);에서 10이라는 값이 들어가는 거 아니야?
그럼 p = 10이 되는 게 아닌가?”

이건 C 언어의 포인터 개념주소 전달 vs 값 전달 차이를 아주 잘 이해해야 하는 부분이에요.
지금 바로 디버깅 수준으로 완전히 해부해서 설명해드릴게요.


💡 먼저 코드부터 다시 보자:

void change(int* p) {
    *p = 100;
}

int main() {
    int a = 10;
    change(&a);
    printf("a = %d\n", a);
}

✅ 지금 이 코드에서 일어나는 일 (상황 재연)

🔸 int a = 10;

  • 변수 a는 정수형이며, 값은 10입니다.
  • 메모리 어딘가에 a가 저장되어 있고, 예를 들어 주소가 0x1000이라 가정해봅시다.
[메모리 예시]
주소:   0x1000
내용:   10   (a의 값)

🔸 change(&a);

  • &a는 a의 주소이므로, 실제로는 change(0x1000);처럼 동작합니다.
  • 즉, 10이 전달되는 게 아니라 → a가 저장된 주소값이 전달됩니다.

🔸 함수로 넘어가기

void change(int* p) {
    *p = 100;
}
  • 여기서 p포인터이고, 그 안에는 0x1000이라는 주소가 들어 있음
  • *p = 100;은 무슨 의미냐면?

p가 가리키는 주소(= a가 저장된 주소)에 100을 써넣으라는 뜻입니다

[p = 0x1000]
[*p = 100] → 즉, 0x1000 주소에 있는 값을 100으로 바꿔라

🔸 그 결과 메모리는 이렇게 바뀜:

주소:   0x1000
내용:   100   ← 원래 10이었지만 이제는 바뀜!

🔸 마지막 줄

printf("a = %d\n", a);  // a는 실제로 100으로 바뀌었음

→ 출력: a = 100


🧠 질문에 대한 답 정리:

"그럼 change(&a)에서 a가 10이면, 10이 전달되는 거 아냐?"

👉 아니에요!
전달되는 것은 10이라는 값이 아니라 a의 주소입니다.
int* p는 그 주소를 받아서,
그 주소에 저장된 값을 100으로 바꾸는 작업을 합니다.


✅ 핵심 차이 비교

호출 형태함수에서 의미원본 바뀌나?
change(a);10이 복사되어 전달됨❌ X
change(&a);a의 주소가 전달됨✅ O
함수 매개변수int p (값)
int* p (주소/참조)

🔁 비유로 쉽게 이해하기:

  • a = 10은 "책상 위에 10이라는 숫자가 적힌 종이"
  • change(a)는 → 그 종이를 복사해서 갖다주는 것 (원본 안 바뀜)
  • change(&a)는 → **종이의 위치(책상 주소)**를 알려주는 것
  • *p = 100; → 그 위치에 가서 직접 값을 고쳐 쓰는 것

좋아요!
이번엔 당신이 직접 눈으로 정확한 차이를 비교할 수 있게,
다음 두 함수를 같은 코드 흐름 안에서 비교해서 보여드릴게요.


✅ 비교 예제: int p vs int* p

#include <stdio.h>

// 값으로 전달 (복사본)
void changeByValue(int p) {
    p = 100;
}

// 주소로 전달 (참조)
void changeByPointer(int* p) {
    *p = 200;
}

int main() {
    int a = 10;

    printf("초기값 a = %d\n", a);

    changeByValue(a);         // 🔹 값만 넘김 (복사본)
    printf("changeByValue 후 a = %d\n", a);  // a는 그대로 10

    changeByPointer(&a);      // 🔹 주소 넘김 (a를 직접 건드림)
    printf("changeByPointer 후 a = %d\n", a); // a는 200으로 바뀜

    return 0;
}

✅ 출력 결과:

초기값 a = 10  
changeByValue 후 a = 10  
changeByPointer 후 a = 200

🔍 흐름 디버깅 해설:

🔸 changeByValue(a);

  • a = 10 → 복사본 p = 10 전달됨
  • p = 100; 은 지역 변수 p만 바꿈
    → 진짜 a건드려지지 않음
a ──┬──▶ 10
    │
    └──→ changeByValue(p = 10) → p = 100  ❌ a에 영향 없음

🔸 changeByPointer(&a);

  • &a → a의 주소 (예: 0x1000) 전달됨
  • *p = 200;a가 저장된 메모리 위치에 직접 200 저장!
a ──▶ 10
         ▲
         └── changeByPointer(p = &a) → *p = 200  ✅ a 직접 변경

✅ 도식 요약:

함수 호출 방식내부 매개변수값 변경?이유
changeByValue(a)int p값 복사, 원본과 무관
changeByPointer(&a)int* p주소 전달, 원본 직접 접근

💡 결론 한 줄 요약:

값 전달(int)은 복사본만 바꾸고,
참조 전달(int*)은 원본을 직접 바꾼다.


🧠 이해 확인용 퀴즈:

다음 코드에서 b의 최종 값은?

#include <stdio.h>

void test(int b) {
    b += 5;
}

int main() {
    int b = 20;
    test(b);
    printf("b = %d\n", b);  // ???
    return 0;
}

오! 그렇게 답할 수 있는 이유를 갖고 계신 건 아주 좋지만,
이 문제의 정답은 사실… 20입니다.
그 이유를 디버깅하듯 완전 해부해서 설명해드릴게요!


✅ 문제 코드 다시 보기

#include <stdio.h>

void test(int b) {
    b += 5;
}

int main() {
    int b = 20;
    test(b);
    printf("b = %d\n", b);  // ✅ 실제 출력은?
    return 0;
}

🔍 흐름 따라가기 (디버깅 방식 해설)

🔸 main() 시작

int b = 20;
  • 변수 b는 메모리 어딘가에 저장되고, 값은 20입니다.

🔸 test(b); 호출

  • b의 값 20복사되어 함수로 전달됩니다.
  • 함수 내부에서는 지역변수 b가 새로 만들어집니다.
    (main의 b와는 전혀 다른 존재!)
void test(int b) {
    b += 5;   // 이건 "지역변수 b = 20 + 5 = 25"일 뿐!
}
  • 여기서 b는 25가 되지만,
  • 이 지역변수는 함수가 끝나면 사라집니다.
  • 원래 main에 있던 b는 전혀 손대지 않았습니다.

🔸 다시 main으로 돌아옴

printf("b = %d\n", b);
  • 여전히 main의 b는 20
  • 따라서 출력: b = 20

✅ 최종 정답: b = 20


🧠 핵심 요약

구분설명
test(int b)b는 복사본 → main의 b와 무관
b += 5;지역 b가 25가 될 뿐, 원본은 그대로
출력 결과원본 b는 변하지 않았으므로 20 출력

💡 만약 b를 진짜 바꾸고 싶다면?

void test(int* p) {
    *p += 5;
}

int main() {
    int b = 20;
    test(&b);
    printf("b = %d\n", b);  // ✅ 출력: 25
}
  • &b → b의 주소를 넘김
  • *p += 5 → b의 값을 직접 변경

✔️ 결론

🔸 기본형 변수는 복사되어 전달되므로 원본에 영향 ❌
🔸 주소를 전달해야만 원본에 직접 영향 줄 수 있음 ✅


0개의 댓글