Menu
Coddy logo textTech

구조체 포인터 전달

Coddy C 여정의 Logic & Flow 섹션에 포함된 레슨 — 63개 중 47번째.

구조체를 값으로 전달하는 방식은 데이터를 읽는 용도로는 적합하지만, 구조체 전체가 복사되기 때문에 크기가 큰 구조체의 경우에는 비효율적입니다. 더 중요한 점은, 함수 내부에서 원본 구조체를 수정할 수 없다는 것입니다. 바로 이런 상황에서 구조체 포인터(pointers to structs)를 전달하는 것이 필수적입니다.

구조체 자체 대신 구조체에 대한 포인터를 전달하면, 함수는 원본 구조체의 메모리 주소를 받습니다. 이 방식은 두 가지 주요 장점을 제공합니다: 더 효율적이며(복사 없음) 함수가 원본 데이터를 수정할 수 있게 해줍니다.

구조체 포인터를 인자로 받는 함수의 구문은 다음과 같습니다:

void functionName(struct StructureName *ptr) {
    // ptr->member를 사용하는 함수 본문
}

함수 내부에서 화살표 연산자를 사용하여 구조체 멤버에 접근하고 수정합니다. 포인터를 통해 이루어진 모든 변경 사항은 호출하는 함수에 있는 원래 구조체에 직접적인 영향을 미치므로, 이 방식은 구조체 데이터를 업데이트하거나 변환해야 하는 함수에 매우 적합합니다.

이 기술은 포인터의 강력함과 구조체(structs)의 조직화를 결합하므로, 복잡한 데이터 구조를 다루는 효율적인 C 프로그램을 작성하는 데 필수적입니다.

challenge icon

챌린지

쉬움

효율적인 데이터 수정을 위해 구조체 포인터를 함수에 전달하는 방법을 보여주는 C 프로그램을 작성하세요. 프로그램의 요구 사항은 다음과 같습니다:

  1. 다음 멤버를 포함하는 BankAccount라는 이름의 struct를 정의합니다:
    • 계좌 번호를 저장할 정수형 accountNumber
    • 계좌 소유주의 이름을 저장할 크기 30의 문자 배열 ownerName
    • 계좌 잔액을 저장할 실수형 balance
    • 거래 횟수를 저장할 정수형 transactionCount
  2. 다음 기능을 수행하는 depositMoney 함수를 작성합니다:
    • BankAccount 구조체 포인터와 실수형 금액(amount)을 매개변수로 받습니다.
    • 화살표 연산자(arrow operator)를 사용하여 계좌 잔액에 금액을 더합니다.
    • 거래 횟수를 1 증가시킵니다.
    • Deposit successful. New balance: [balance]를 출력합니다.
  3. 다음 기능을 수행하는 withdrawMoney 함수를 작성합니다:
    • BankAccount 구조체 포인터와 실수형 금액(amount)을 매개변수로 받습니다.
    • 출금 금액이 현재 잔액보다 큰지 확인합니다.
    • 잔액이 부족하면, Insufficient funds. Current balance: [balance]를 출력합니다.
    • 잔액이 충분하면, 잔액에서 금액을 차감하고 거래 횟수를 증가시킨 후, Withdrawal successful. New balance: [balance]를 출력합니다.
  4. 다음 기능을 수행하는 displayAccount 함수를 작성합니다:
    • BankAccount 구조체 포인터를 매개변수로 받습니다.
    • 다음과 같은 정확한 형식으로 계좌 정보를 출력합니다:
      • Account Information:
      • Account Number: [accountNumber]
      • Owner: [ownerName]
      • Balance: [balance]
      • Transactions: [transactionCount]
  5. main 함수에서 다음을 수행합니다:
    • account라는 이름의 BankAccount 변수를 생성합니다.
    • 입력으로부터 계좌 번호, 소유주 이름, 초기 잔액을 읽어옵니다.
    • 거래 횟수를 0으로 설정합니다.
    • displayAccount를 호출하여 초기 계좌 상태를 보여줍니다.
    • 입금액을 읽어와 depositMoney를 호출합니다.
    • 출금액을 읽어와 withdrawMoney를 호출합니다.
    • displayAccount를 호출하여 최종 계좌 상태를 보여줍니다.

이 챌린지는 구조체 포인터를 함수에 전달하는 방식의 강력함을 보여줍니다. 값에 의한 전달(pass-by-value)과 달리, 함수는 원본 구조체의 메모리 주소를 전달받으므로 원본 데이터를 직접 수정할 수 있습니다. 이 방식은 복사가 발생하지 않아 더 효율적이며, 함수가 호출한 쪽의 구조체 값을 영구적으로 변경할 수 있게 해줍니다.

치트 시트

구조체를 값으로 전달할 때, 전체 구조체가 복사되므로 큰 구조체의 경우 비효율적이며 원본 데이터를 수정할 수 없습니다. 구조체 포인터를 전달하면 대신 메모리 주소를 전달함으로써 이 두 가지 문제를 모두 해결할 수 있습니다.

구조체 포인터를 받기 위한 함수 구문:

void functionName(struct StructureName *ptr) {
    // ptr->member를 사용하는 함수 본문
}

함수 내부에서는 화살표 연산자(->)를 사용하여 포인터를 통해 구조체 멤버에 접근하고 수정합니다. 변경된 사항은 호출한 함수의 원본 구조체에 직접적인 영향을 미칩니다.

이 방식은 두 가지 주요 장점을 제공합니다:

  • 더 효율적임 (전체 구조체를 복사하지 않음)
  • 함수가 원본 구조체 데이터를 수정할 수 있도록 허용함

직접 해보기

#include <stdio.h>
#include <string.h>

// TODO: 여기에 BankAccount 구조체를 정의하세요

// TODO: 여기에 depositMoney 함수를 작성하세요

// TODO: 여기에 withdrawMoney 함수를 작성하세요

// TODO: 여기에 displayAccount 함수를 작성하세요

int main() {
    // 입력 읽기
    int accountNum;
    char ownerName[30];
    float initialBalance;
    float depositAmount;
    float withdrawAmount;
    
    scanf("%d", &accountNum);
    scanf("%s", ownerName);
    scanf("%f", &initialBalance);
    scanf("%f", &depositAmount);
    scanf("%f", &withdrawAmount);
    
    // TODO: BankAccount 변수를 생성하고 초기화하세요
    
    // TODO: 초기 상태를 표시하기 위해 displayAccount를 호출하세요
    
    // TODO: 입금액과 함께 depositMoney를 호출하세요
    
    // TODO: 출금액과 함께 withdrawMoney를 호출하세요
    
    // TODO: 최종 상태를 표시하기 위해 displayAccount를 호출하세요
    
    return 0;
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

Logic & Flow의 모든 레슨