개발 | C언어

배열 다루기: main 함수 외부에서 return이 필요 없는 이유와 scanf 사용법

devwithham 2024. 12. 5. 19:47
반응형

배열 다루기: main 함수 외부에서 return이 필요 없는 이유와 scanf 사용법

안녕하세요, 개발자 여러분! 오늘은 C 언어에서 배열을 함수 외부에서 다룰 때 return이 필요 없는 이유와 scanf 함수와의 관계에 대해 깊이 있게 알아보겠습니다. 배열의 특성과 scanf 함수의 사용 방식을 이해하면 보다 효율적이고 깔끔한 코드를 작성할 수 있습니다. 그럼 시작해볼까요?


1. 배열의 참조 타입 특성

배열은 기본적으로 **참조 타입(reference type)**으로 취급됩니다. 이는 배열의 실제 데이터가 아니라 배열의 메모리 주소가 함수로 전달된다는 의미입니다. 따라서 함수 내부에서 배열의 값을 수정하면, 그 변경 사항이 함수 외부에도 그대로 반영됩니다. 이러한 특성 덕분에 배열을 다룰 때 별도로 return을 사용하지 않아도 됩니다.

참조 타입과 값 타입의 차이

  • 값 타입(Value Type): 함수에 인자로 전달될 때 실제 값이 복사되어 전달됩니다. 함수 내부에서 값을 변경해도 외부에는 영향을 미치지 않습니다.
  • 참조 타입(Reference Type): 함수에 인자로 전달될 때 값의 주소(참조)가 전달됩니다. 함수 내부에서 값을 변경하면 외부에서도 그 변경이 그대로 반영됩니다.

2. 배열을 함수의 인자로 전달하는 방식

C 언어에서는 배열을 함수에 전달할 때 배열의 메모리 주소가 전달됩니다. 이를 통해 함수는 배열의 원본 데이터를 직접 수정할 수 있습니다. 다음은 C 언어에서 배열을 함수에 전달하는 예제입니다.

C 언어 예제

#include <stdio.h>

// 배열을 수정하는 함수
void modifyArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        arr[i] *= 2;  // 배열 원소 값을 두 배로 변경
    }
}

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    modifyArray(arr, 5);  // 배열을 함수에 전달

    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);  // 변경된 배열 출력
    }

    return 0;
}

위 코드에서 modifyArray 함수는 배열의 원소 값을 두 배로 변경하지만, return을 사용하지 않습니다. 그럼에도 불구하고 main 함수에서 배열을 출력할 때 이미 변경된 값이 반영됩니다. 이는 배열의 주소를 통해 원본 배열을 직접 수정했기 때문입니다.

3. 배열과 scanf의 관계

배열은 일반적으로 배열 이름이 배열의 시작 주소를 나타내는 포인터처럼 동작합니다. 따라서 배열을 사용할 때 배열의 이름을 그대로 쓰면 해당 배열의 첫 번째 요소의 주소를 의미하게 됩니다. scanf 함수와 배열을 함께 사용할 때의 예제를 통해 이를 더 자세히 살펴보겠습니다.

배열의 사용 예시

1. 정수 배열의 경우 (int array[])

#include <stdio.h>

int main() {
    int array[5];
    
    printf("5개의 정수를 입력하세요:\n");
    for (int i = 0; i < 5; i++) {
        scanf("%d", &array[i]);  // 배열의 특정 요소의 주소를 전달
    }

    printf("입력된 배열: ");
    for (int i = 0; i < 5; i++) {
        printf("%d ", array[i]);
    }

    return 0;
}

위 예제에서 scanf 함수는 &array[i]를 사용하여 배열의 특정 요소에 값을 저장합니다. 배열 이름 자체가 배열의 시작 주소를 나타내지만, 특정 요소에 값을 저장하기 위해서는 해당 요소의 주소를 전달해야 합니다.

2. char 배열의 경우 (문자열과 단일 문자)

문자열 입력 (char Name[])

#include <stdio.h>

int main() {
    char Name[100];
    
    printf("이름을 입력하세요: ");
    scanf("%s", Name);  // 문자열 입력 시 주소 연산자 없이 사용

    printf("입력된 이름: %s\n", Name);
    
    return 0;
}

문자열은 여러 문자가 연속으로 저장되는 배열입니다. 문자열의 경우 배열 이름 (Name) 자체가 문자열의 시작 주소를 나타내므로, scanf에서 주소 연산자 없이 Name을 그대로 사용할 수 있습니다.

단일 문자 입력 (char English[])

#include <stdio.h>

int main() {
    char English[10];
    
    printf("문자들을 입력하세요: ");
    for (int i = 0; i < 10; i++) {
        scanf(" %c", &English[i]);  // 단일 문자 입력 시 주소 연산자 사용
    }

    printf("입력된 문자들: ");
    for (int i = 0; i < 10; i++) {
        printf("%c ", English[i]);
    }

    return 0;
}

단일 문자를 입력할 때는 배열의 특정 요소에 접근하여 값을 저장해야 하므로 &English[i]와 같이 주소 연산자를 사용해야 합니다.

정리

  • 정수 배열 (int array[]): 특정 요소에 값을 저장할 때는 해당 요소의 주소 (&array[i])를 전달해야 합니다.
  • 문자열 배열 (char Name[]): 문자열 전체를 입력할 때는 배열 이름 자체가 주소이므로 주소 연산자를 생략할 수 있습니다.
  • 단일 문자 배열 (char English[]): 특정 요소에 값을 저장할 때는 주소 연산자를 사용해야 합니다.

따라서, 정수형 배열이나 단일 문자 배열 모두 scanf를 사용할 때 특정 요소에 값을 저장하려면 주소 연산자를 사용해야 합니다. 하지만 문자열 배열의 경우에는 배열 이름 자체가 포인터처럼 동작하기 때문에 주소 연산자를 생략할 수 있습니다.

4. 왜 return이 필요 없는가?

배열이나 리스트와 같은 참조 타입은 함수에 전달될 때 그 메모리 주소가 전달되기 때문에, 함수 내부에서 직접 원본 데이터를 수정할 수 있습니다. 따라서 함수가 배열을 수정한 후 별도로 값을 반환할 필요가 없습니다. 이는 코드의 간결성을 유지하고, 불필요한 복사를 방지하여 성능을 향상시키는 데에도 도움이 됩니다.

장점 정리

  • 성능 향상: 데이터의 복사를 피할 수 있어 메모리 사용량과 처리 속도가 개선됩니다.
  • 코드 간결성: 불필요한 반환문을 제거하여 코드가 더 깔끔해집니다.
  • 직접 수정 가능: 함수 내부에서 원본 데이터를 직접 수정할 수 있어 유연성이 높아집니다.

5. 주의할 점

참조 타입을 사용할 때는 원본 데이터가 의도치 않게 수정될 수 있다는 점을 유의해야 합니다. 특히 여러 함수에서 동일한 배열을 참조하여 수정할 경우, 예상치 못한 버그가 발생할 수 있습니다. 이를 방지하기 위해 필요한 경우 데이터의 복사본을 만들어 사용하는 것이 좋습니다.


이 글에서는 배열이 참조 타입으로 처리되어 함수 외부에서 return이 필요 없는 이유와 scanf 함수와의 관계를 살펴보았습니다. 배열을 효과적으로 다루기 위해 이러한 특성을 이해하고 활용하는 것이 중요합니다. 더 많은 프로그래밍 팁과 정보를 원하신다면 저희 블로그를 계속 주목해 주세요!

 

반응형