값 전달3

류한선·2025년 6월 28일

실기연습-2

목록 보기
55/95

정말 좋은 질문이에요!
그리고 이 질문을 하신 걸 보면 C언어의 “값 전달”과 “변수의 생명 주기(scope)”를 거의 다 이해하셨다는 뜻이에요.
이제 이 개념을 완전히 마무리할 수 있도록,
아래 코드를 디버깅 하듯이 한 줄 한 줄 해부하면서
temp 값이 누적되는지 완벽하게 설명드릴게요.


✅ 질문 코드 다시 보기

#include <stdio.h>

int main() {
    int sum = 0;
    int temp = 0;

    for (int i = 0; i < 3; i++) {
        temp += i;
        sum += temp;
    }

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

❓질문 요점:

tempint형이고,
아까 int형은 값이 복사되기 때문에 원본에 영향이 없다고 했는데,
왜 여기서는 temp가 누적돼?


✅ 핵심 차이 정리

✔️ 값 전달이란?

함수의 매개변수로 int x를 넘겼을 때, x는 복사본 → 원본 변수와는 연결 X

📌 이건 “함수 호출 시 전달 방식”에만 해당됩니다!


⛔ 지금은 함수가 아니라 main 함수 안의 반복문입니다!

int temp = 0;  // ⬅️ 이 변수는 main 함수 전체에서 살아있음

즉, temp는 main 함수의 지역 변수이고,
for문 안에서도 계속 같은 temp를 사용하고 있는 거예요.


🔍 실행 흐름 완전 해부

int sum = 0;
int temp = 0;
  • sum, temp 모두 한 번만 선언됨
  • 이 변수들은 main 함수가 끝날 때까지 살아 있음

for (int i = 0; i < 3; i++) {
    temp += i;
    sum += temp;
}

반복1: i = 0

  • temp += 0 → temp = 0 + 0 = 0
  • sum += 0 → sum = 0 + 0 = 0

반복2: i = 1

  • temp += 1 → temp = 0 + 1 = 1
  • sum += 1 → sum = 0 + 1 = 1

반복3: i = 2

  • temp += 2 → temp = 1 + 2 = 3
  • sum += 3 → sum = 1 + 3 = 4

출력:

printf("sum = %d\n", sum);  // 🔸 4 출력됨

✅ 정리: 왜 temp가 누적되는가?

temp 선언 위치의미
for문 ➤ 단 한 번 생성됨 → 매 반복 때 기존 값 유지
for문 에 있으면➤ 매 반복마다 새롭게 0으로 초기화됨

🧠 핵심 요약

  • int형이 "값만 복사된다"는 건 함수에 전달할 때 이야기
  • 지금처럼 같은 함수 안에서 변수 사용 시에는
    그 변수가 어디서 선언되었는지가 핵심
  • for문 밖에 선언되었으므로, temp는 매번 누적됨!

🔁 만약 이렇게 바꿨다면?

for (int i = 0; i < 3; i++) {
    int temp = 0;  // 매번 새로 만들어짐
    temp += i;
    sum += temp;
}

실행 결과:

  • temp는 반복할 때마다 0부터 시작 → sum = 0 + 1 + 2 = 3

✅ 완벽 정리 한 문장

📌 “temp가 누적되는 이유는, 함수 호출이 아니라 같은 함수 내 반복문에서 사용되고,
그 temp 변수가 한 번만 선언되고 계속 재사용되기 때문입니다.”


네! 아주 핵심을 정확히 반 이상 이해하셨어요 👏
이제 남은 반을 예시 + 시각화 + 상황별 비교로 완전히 채워드릴게요.


✅ 먼저 결론 요약부터 드리자면:

✔️ 같은 함수(main 함수 포함) 안에 있는 int 변수는
그냥 그 변수 하나만 계속 쓰기 때문에 값이 누적됨

❌ 하지만, 다른 함수에서 int 변수 값을 바꾸려면,
→ 그냥 값만 넘기면 원본은 바뀌지 않음 → 복사본만 바뀜


✅ 이걸 예제로 완전히 이해해보자!


✅ 1) 같은 함수 안에서 temp가 누적되는 경우

#include <stdio.h>

int main() {
    int temp = 0;
    for (int i = 0; i < 3; i++) {
        temp += i;
    }
    printf("temp = %d\n", temp);  // ✅ 0 + 1 + 2 = 3
    return 0;
}
  • tempmain 함수의 지역 변수
  • 한 번만 만들어져서 for문 안에서도 계속 누적 사용

❌ 2) 다른 함수에 넘기면? (값만 전달 → 영향 ❌)

#include <stdio.h>

void update(int temp) {
    temp += 100;
}

int main() {
    int temp = 0;
    for (int i = 0; i < 3; i++) {
        update(temp);     // ❌ temp는 바뀌지 않음
    }
    printf("temp = %d\n", temp);  // 🔸 여전히 0
    return 0;
}

📌 이 경우는 temp가 함수로 넘겨질 때 값만 복사됨
함수 안에서 바꿔봤자 → main 함수의 temp에는 영향 없음


✅ 3) 다른 함수에서 바꾸고 싶으면? 포인터 써야 함

#include <stdio.h>

void update(int* p) {
    *p += 100;
}

int main() {
    int temp = 0;
    for (int i = 0; i < 3; i++) {
        update(&temp);  // ✅ 주소를 넘겨서 직접 temp를 바꿈
    }
    printf("temp = %d\n", temp<);  // 🔸 출력: 300
    return 0;
}
  • update(&temp) → temp의 주소를 넘김
  • *p += 100; → temp의 실제 메모리를 수정
  • 매 반복마다 100씩 더함 → 100 + 100 + 100 = 300

📊 비교표로 정리

상황temp 위치함수에서 전달 방식결과
main 함수 안지역 변수직접 누적 가능✅ 누적됨
함수로 넘김지역 변수값만 복사 (int)❌ 안 바뀜
함수로 넘김지역 변수주소 넘김 (int*)✅ 바뀜

🧠 결론

🔸 main 함수 안에 있으면 그냥 그 변수를 쓰기 때문에 누적됨
🔸 main 함수 밖의 함수에 값을 전달하면 복사본만 전달되기 때문에 안 바뀜
🔸 그 변수의 주소(=참조)를 넘기면 바뀐다!


📌 마지막 요약 문장

✔️ “같은 함수 안에 있으면 변수는 계속 살아 있어서 누적되고,
다른 함수에서 바꾸려면 값을 넘기면 안 되고,
주소를 넘겨야 한다.”


네, 아주 좋은 질문입니다! 👍
결론부터 말하면:

C 언어에서는 함수(function)라는 말만 씁니다.
update()함수입니다.
❌ C에는 **메서드(method)**라는 개념이 없습니다.


📌 함수 vs 메서드 — 차이점 요약

구분함수 (Function)메서드 (Method)
어디서 사용?C, Python 등Java, C++, Python 등
특징독립적인 코드 블록클래스 내부에 소속됨
this 포인터?없음있음 (this 사용 가능)
대표 언어C, Go, PythonJava, C++, Python

🔍 예시 비교

✅ C 언어: 함수 (Function)

void update(int* p) {
    *p = 100;
}
  • 클래스나 객체와 무관하게 동작
  • 독립적인 코드 블록
  • 함수(Function) 이라고 부름

✅ Java: 메서드 (Method)

class Example {
    void update() {
        System.out.println("Hello");
    }
}
  • 클래스 내부에 있음
  • 객체가 있어야 호출 가능
  • 메서드(Method) 라고 부름

🧠 C 언어에서는 왜 "메서드"가 없을까?

  • C는 객체 지향 언어가 아닙니다.
  • 클래스나 객체 개념이 없고,
  • 모든 것은 전역 함수 또는 지역 함수로 동작합니다.

따라서 main(), update() 같은 건 모두 **"함수(function)"**입니다.
Java처럼 this로 객체 상태를 조작하는 방식은 아예 존재하지 않죠.


✅ 결론 정리

  • update()는 C 언어 기준에서 보면 함수입니다.
  • 메서드는 클래스 안에 들어간 함수일 때 사용하는 용어이며,
    C에는 해당 개념이 없어요!

와, 정말 날카로운 질문이에요! 👍
**“자바에서 메서드니까 값에 영향을 받는가?”**라는 질문은,
사실 이렇게 정리할 수 있어요:

“메서드라서 값에 영향을 받는다”는 말은 정확하지 않아요.
자바도 값에 영향을 주느냐 마느냐는 '자료형'에 따라 달라져요.


✅ 요약부터 말하면

구분자바에서의 동작
int, double, boolean 등 기본형✅ 값만 복사됨 → 원본 영향 ❌
객체 (String, ArrayList, 배열 등)✅ 주소(참조)가 복사됨 → 원본 영향 가능 ✅

📌 핵심: 자바는 무조건 "값에 의한 전달"이다.

다만 **"값 자체가 '참조(주소)'일 수 있다"**는 게 핵심이에요!


✅ 예제 1: 기본형(int) — 영향 없음

public class Test {
    static void change(int x) {
        x = 100;
    }

    public static void main(String[] args) {
        int a = 10;
        change(a);
        System.out.println(a); // ✅ 출력: 10
    }
}
  • a값 10이 복사돼서 x로 전달됨
  • x를 바꿔도 a는 영향 X

✅ 예제 2: 객체 (배열, ArrayList 등) — 영향 있음

public class Test {
    static void change(int[] arr) {
        arr[0] = 100;
    }

    public static void main(String[] args) {
        int[] a = {10, 20, 30};
        change(a);
        System.out.println(a[0]); // ✅ 출력: 100
    }
}
  • 배열은 참조 타입
  • arr에는 a의 주소가 복사되어 들어감
  • arr[0] = 100 → 실제 a[0]을 수정함

✅ 결론 정리

질문답변
자바는 메서드니까 값이 바뀌는가?❌ 아니요. 메서드여도 기본형은 복사됨 (원본 영향 ❌)
자바는 객체는 왜 바뀌는가?✅ 참조(주소)를 복사하므로 원본이 바뀔 수 있음
자바는 참조 전달인가요?❌ 아니요. 자바는 값 전달만 존재함. 단, 그 값이 참조(주소)일 수 있음

🧠 기억하기 쉽게 요약!

✔️ 자바는 항상 값 전달(pass-by-value)
✔️ 기본형: 값이 복사됨 → 영향 ❌
✔️ 참조형(배열, 객체 등): 주소가 복사됨 → 원본 영향 가능 ✅


좋아요! 지금까지 배운
값 전달 vs 참조 전달 (기본형 vs 참조형),
C와 Java에서의 차이,
변수가 영향을 받는가? 이 개념들을
완전히 복습할 수 있도록 문제를 단계별로 낼게요.


✅ 문제 1. (Java 기본형)

다음 코드의 출력 결과는?

public class Test {
    static void change(int x) {
        x += 5;
    }

    public static void main(String[] args) {
        int a = 10;
        change(a);
        System.out.println("a = " + a);
    }
}

Q: 출력 결과는 무엇인가요?


✅ 문제 2. (Java 참조형)

public class Test {
    static void change(int[] arr) {
        arr[1] = 999;
    }

    public static void main(String[] args) {
        int[] nums = {1, 2, 3};
        change(nums);
        System.out.println<("nums[1] = " + nums[1]);
    }
}

Q: 출력 결과는 무엇인가요?


✅ 문제 3. (C 기본형)

#include <stdio.h>

void update(int x) {
    x = x + 10;
}

int main() {
    int a = 5;
    update(a);
    printf("a = %d\n", a);
    return 0;
}

Q: 출력 결과는 무엇인가요?


✅ 문제 4. (C 포인터)

#include <stdio.h>

void update(int* p) {
    *p = *p + 10;
}

int main() {
    int a = 5;
    update(&a);
    printf("a = %d\n", a);
    return 0;
}

Q: 출력 결과는 무엇인가요?


🔍 추가 설명 문제 (객관식)

문제 5. 다음 중 ‘값이 실제로 변경되는 경우’를 모두 고르세요.

  1. Java에서 void f(int x)int 전달
  2. Java에서 void f(int[] arr)로 배열 전달
  3. C에서 void f(int x)로 int 전달
  4. C에서 void f(int* p)로 포인터 전달

좋습니다! 각 문제에 대한 정답과 자세한 이유를 하나씩 디버깅 흐름처럼 설명해드릴게요.


✅ 문제 1: Java에서 int 전달

public class Test {
    static void change(int x) {
        x += 5;
    }

    public static void main(String[] args) {
        int a = 10;
        change(a);
        System.out.println("a = " + a);
    }
}

🔍 흐름

  • change(a) → a의 값 10이 복사되어 x로 전달됨
  • x += 5 → x는 15가 되지만, main의 a는 바뀌지 않음
  • 출력: "a = 10"

✅ 정답: a = 10


✅ 문제 2: Java에서 배열 전달

static void change(int[] arr) {
    arr[1] = 999;
}

🔍 흐름

  • int[] nums = {1, 2, 3}
  • change(nums)배열 주소가 전달됨
  • arr[1] = 999 → nums[1]을 직접 바꿈
  • 출력: "nums[1] = 999"

✅ 정답: nums[1] = 999


✅ 문제 3: C에서 int 값만 전달

void update(int x) {
    x = x + 10;
}

🔍 흐름

  • update(a) → 값 5가 복사되어 x로 전달
  • x = x + 10 → x는 15가 되지만, a는 그대로
  • 출력: "a = 5"

✅ 정답: a = 5


✅ 문제 4: C에서 포인터로 전달

void update(int* p) {
    <*p = *p + 10;
}

🔍 흐름

  • update(&a) → a의 주소 전달
  • *p = *p + 10 → a의 값을 직접 수정
  • a = 5 + 10 = 15
  • 출력: "a = 15"

✅ 정답: a = 15


✅ 문제 5: 어느 경우에 값이 실제로 바뀌는가?

다음 중 ‘값이 실제로 변경되는 경우’를 모두 고르세요.

선택지상황 설명값이 바뀌는가?
1번Java에서 int 전달❌ 복사본만 변경
2번Java에서 int[] 배열 전달✅ 참조값 복사, 실제 배열 변경됨
3번C에서 int 값 전달❌ 복사본만 변경
4번C에서 int* 포인터 전달✅ 실제 변수의 메모리 직접 수정

✅ 정답: 2번, 4번


🎯 핵심 복습 요약:

언어기본형(int 등) 전달참조형(배열, 포인터 등) 전달
Java값 복사 (원본 변경 ❌)참조 복사 (원본 변경 가능 ✅)
C값 복사 (원본 변경 ❌)주소 전달 (원본 변경 가능 ✅)

좋아요! 😈
이번엔 정말 대충 이해했으면 틀릴 수밖에 없는,
헷갈리는 요소를 가득 넣은 문제를 드릴게요.
단순한 개념 암기만으로는 절대 못 푸는 문제로 구성했습니다.
(그러면서도 본질은 기본 개념입니다!)


✅ 문제 1. (Java, 배열 안에서 새 배열 할당)

public class Test {
    static void change(int[] arr) {
        arr = new int[]{9, 9, 9};  // 🔥 배열 자체를 새로 만듦!
        arr[0] = 100;
    }

    public static void main(String[] args) {
        int[] nums = {1, 2, 3};
        change(nums);
        System.out.println("nums[0] = " + nums[0]);
    }
}

Q: nums[0]의 출력 결과는 무엇일까요?


✅ 문제 2. (C, 포인터처럼 보이지만 복사본만 건드는 트릭)

#include <stdio.h>

void update(int* p) {
    int x = *p;
    x += 10;
    p = &x;
}

int main() {
    int a = 5;
    update(&a);
    printf("a = %d\n", a);
    return 0;
}

Q: a의 최종 값은?


✅ 문제 3. (Java, 참조형 같지만 내부 객체는 새로 만듦)

class Data {
    int x;
}

public class Test {
    static void change(Data d) {
        d = new Data();   // 🔥 새로운 객체 생성
        d.x = 999;
    }

    public static void main(String[] args) {
        Data d = new Data();
        d.x = 100;
        change(d);
        System.out.println("d.x = " + d.x);
    }
}

Q: d.x의 최종 출력값은?


✅ 문제 4. (C, 배열 주소 전달과 배열 복사 헷갈리게)

#include <stdio.h>

void change(int arr[]) {
    arr = (int[]){9, 9, 9};  // ❌ 이건 컴파일 안 될 수도 있어요, 유사한 트릭입니다
    arr[0] = 100;
}

int main() {
    int nums[] = {1, 2, 3};
    change(nums);
    printf("nums[0] = %d\n", nums[0]);
    return 0;
}

Q: nums[0]의 출력 결과는?


✅ 문제 5. (Java, 메서드 내부에서 참조형을 재사용하는 듯한 상황)

public class Test {
    static void modify(String s) {
        s = s.toUpperCase();
    }

    public static void main(String[] args) {
        String str = "hello";
        modify(str);
        System.out.println(str);
    }
}

Q: 최종 출력 결과는?


좋습니다! 😎
지금부터 문제 하나하나 디버깅 수준으로 흐름을 완전히 해부해서
“어디서 왜 틀릴 수밖에 없었는지”까지 확실히 이해시키겠습니다.


✅ 문제 1. Java – 배열 자체를 새로 만든 경우

static void change(int[] arr) {
    arr = new int[]{9, 9, 9};  // ❗ arr가 가리키는 배열 자체를 바꿔버림
    arr[0] = 100;
}

public static void main(String[] args) {
    int[] nums = {1, 2, 3};
    change(nums);
    System.out.println("nums[0] = " + nums[0]);
}

🔍 해설

  • change(nums) 호출 시 nums의 주소(참조)가 arr로 복사됨

  • 그러나 arr = new int[]{9, 9, 9} 이 부분에서,

    • arr는 새로운 배열을 가리키게 됨!
    • 기존 nums와는 연결이 끊어짐
  • 이후 arr[0] = 100은 → 새 배열의 0번째에 저장됨
    (nums는 그대로 유지)

✅ 정답: nums[0] = 1


✅ 문제 2. C – 포인터 같은데 값 안 바뀜

void update(int* p) {
    int x = *p;
    x += 10;
    p = &x;  // ❗ 포인터 자체를 바꿔버림 (실제 값에는 영향 없음)
}

🔍 해설

  1. p&a를 받아서 a의 주소를 가리킴 (예: p → 0x1000)
  2. x = *p → x = 5
  3. x += 10 → x = 15
  4. p = &x → p가 x를 가리키게 바뀜 → a와는 무관해짐
  5. 함수 종료 → x는 사라짐 → a는 바뀌지 않음

✅ 정답: a = 5


✅ 문제 3. Java – 객체 안에서 새 객체 만들기

static void change(Data d) {
    d = new Data();   // ❗ d는 새로운 객체를 가리킴 (원본과 끊김)
    d.x = 999;
}

🔍 해설

  1. change(d) 호출 시, d의 참조(주소)가 복사됨
  2. d = new Data() → d가 새로운 객체를 가리킴
    원래 main에 있던 d와 연결 끊김
  3. d.x = 999은 새 객체에 저장된 값
  4. main의 d.x는 여전히 100

✅ 정답: d.x = 100


✅ 문제 4. C – 배열 바꾸는 척 하지만 실패

이 문제는 일부 컴파일러에서는 안 돌아갈 수 있어요.
원래는 이런 구조를 사용할 수 없지만, 핵심 개념을 설명하기 위해 비슷한 구조로 풀게요.

void change(int arr[]) {
    arr = (int[]){9, 9, 9}; // ❗ 배열 포인터를 바꿈
    arr[0] = 100;
}

🔍 해설

  • C에서 arr는 사실상 int* arr로 해석됨 (배열의 주소)
  • arr = ... → arr가 가리키는 배열을 새로운 배열로 교체
  • 하지만 main 함수의 nums[]는 여전히 원래 배열을 가리킴
  • arr[0] = 100은 새 배열의 값 → nums는 변함 없음

✅ 정답: nums[0] = 1


✅ 문제 5. Java – 문자열 참조 바꾸기

static void modify(String s) {
    s = s.toUpperCase();
}

🔍 해설

  • Java의 Stringimmutable (불변 객체)
  • s.toUpperCase()는 새로운 문자열 "HELLO"을 생성
  • s = ... → s가 새 문자열을 가리키게 됨
  • 하지만 main의 str은 여전히 "hello"

✅ 정답: "hello"


🎯 전체 정답 요약

문제 번호정답 출력이유 요약
문제 1nums[0] = 1배열 자체를 새로 만들어 연결이 끊김
문제 2a = 5포인터를 다른 변수(x)로 바꿔버림
문제 3d.x = 100객체 자체를 새로 만들어 원본과 끊어짐
문제 4nums[0] = 1배열 포인터만 바꿈 (원래 배열 영향 없음)
문제 5hello문자열은 불변, 참조만 바뀜 → 원본 그대로

🧠 결론 요약

  • 참조형도 주소를 새로 바꾸면 원본은 영향을 안 받는다.
  • 포인터도, 객체도 '새로 만든다'는 건 '끊긴다'는 뜻이다.
  • 단순히 "참조니까 무조건 바뀜"이 아니라,
    **"같은 메모리를 가리키고 있느냐"**가 핵심이에요.

정확히 봤어요! 👏
거의 완벽한 이해에 도달하셨고,
한 단계만 더 구체화하면 완전 마스터입니다.


✅ 당신의 정리 (요약)

변수가 선언된 범위 안에서만 쓰이면 계속 누적되고 영향이 있지만,
그 범위를 벗어나서 다른 함수 등으로 연동될 때는
➤ **배열이나 포인터(=참조형)**가 아닌 이상, 값은 안 바뀐다 ❞

🟢 거의 정확해요!
이걸 더 명확히 하자면 이렇게 됩니다:


🎯 최종 개념 정리: "변수의 영향 범위"

상황예시값이 바뀜?이유
같은 함수 안for문 안에서 int temp 계속 누적✅ 바뀜같은 변수이기 때문에 그대로 영향 받음
함수로 값을 넘김 (int x)change(int x)❌ 안 바뀜값이 복사되기 때문
함수로 주소를 넘김 (int* p, int[] arr)change(int* p) / change(int[] arr)✅ 바뀜메모리 주소를 통해 원본 직접 수정
함수 안에서 참조형 자체를 새로 생성함arr = new int[3]; / obj = new Obj();❌ 원본과 끊어짐참조가 바뀌었을 뿐, 원본은 유지됨
문자열과 같이 불변 객체 (Java String)str = str.toUpperCase();❌ 바뀌지 않음새 객체 생성됨. 원본은 그대로

💡 포인트: 변수 영향 여부를 판단할 때 중요한 3가지 질문

  1. 지금 이 변수는 "같은 공간을 공유"하고 있는가?
  2. 값만 넘겼는가, 주소(참조)를 넘겼는가?
  3. 중간에 참조가 새 걸로 바뀌진 않았는가?

✅ 당신이 이해한 문장을 수정 없이 바꿔서 정리하면:

✔️ 같은 범위(=같은 함수, 같은 객체 안)에서 사용하면 영향 받는다.
✔️ 그 범위를 벗어나 다른 함수로 전달되는 경우는,
➤ 배열이나 포인터처럼 주소가 전달되는 경우만 원본에 영향을 준다.

완벽합니다. 🎯


0개의 댓글