Computer >> 컴퓨터 >  >> 프로그래밍 >> C 프로그래밍

C 언어에서 함수 인수로 구조체 주소를 전달하는 방법


구조체 값을 전달하는 세 가지 방법

C 언어에서 구조체의 값을 한 함수에서 다른 함수로 전달하는 방법은 크게 세 가지가 있습니다.

  • 개별 멤버를 함수의 인수로 전달하는 방법

  • 구조체 전체를 함수의 인수로 전달하는 방법

  • 구조체의 주소를 함수의 인수로 전달하는 방법

이 글에서는 그중에서도 구조체의 주소를 인수로 전달하는 방법을 중심으로 자세히 살펴보겠습니다.

구조체 주소 전달의 기본 원리

  • 호출하는 쪽에서는 구조체 변수의 주소(&)를 함수의 인수로 넘깁니다.

  • 함수 선언부에서는 이 주소를 구조체 포인터로 받아 처리합니다.

이렇게 하면 함수 내부에서 화살표 연산자(->)를 사용해 구조체의 각 멤버에 자유롭게 접근할 수 있습니다.

장점

구조체의 주소를 함수에 전달하면 다음과 같은 이점이 있습니다.

  • 메모리 낭비가 없습니다. 구조체 복사본을 다시 생성할 필요가 없기 때문입니다.

  • 반환값이 필요 없습니다. 함수가 포인터를 통해 구조체 전체에 간접적으로 접근하여 직접 작업할 수 있기 때문입니다.

예제 1: 날짜 구조체의 주소 전달하기

다음 프로그램은 구조체의 주소를 함수의 인수로 전달하는 가장 기본적인 형태를 보여줍니다.

#include<stdio.h>
struct date{
    int day;
    char month[10];
    int year;
};
int main(){
    struct date d;
    printf("enter the day,month and year:");
    scanf("%d%s%d",&d.day,d.month,&d.year);
    display(&d);  // 구조체의 주소를 인수로 전달
    return 0;
}
void display(struct date *p){  // 구조체 포인터로 주소를 받음
    printf("day=%d\n",p->day);
    printf("month=%s\n",p->month);
    printf("year=%d\n",p->year);
}

실행 결과

enter the day, month and year:20 MAR 2021
day=20
month=MAR
year=2021

main() 함수에서 display(&d)처럼 구조체 변수 앞에 주소 연산자 &를 붙여 호출하면, display() 함수는 struct date * 타입의 포인터 p로 이를 받아 p->day, p->month, p->year와 같이 각 멤버에 접근합니다.

예제 2: 구조체 배열과 포인터 활용하기

다음은 여러 명의 학생 정보를 담는 구조체 배열의 주소를 함수에 전달하는 예제입니다. 함수 안에서 포인터 증감 연산(p++)을 사용해 배열 요소를 하나씩 순회할 수 있으며, 구조체를 복사하지 않고 참조만 하므로 메모리 낭비가 전혀 없습니다.

#include<stdio.h>
// 구조체 선언 //
struct student{
    char Name[100];
    int Age;
    float Level;
    char Grade[50];
    char temp;
}s[5];
// 함수 선언 및 정의 //
void show(struct student *p){
    // 함수 내부에서 사용할 반복문 변수 선언 //
    int i;
    // 출력용 for 반복문 //
    for(i=1;i<3;i++){
        printf("The Name of student %d is : %s\n",i,p->Name);
        printf("The Age of student %d is : %d\n",i,p->Age);
        printf("The Level of student %d is : %f\n",i,p->Level);
        printf("The Grade of student %d is : %s\n",i,p->Grade);
        p++;  // 다음 구조체 요소로 이동
    }
}
void main(){
    // 반복문 변수 선언 //
    int i;
    // 구조체 포인터 선언 //
    struct student *p;
    // 사용자 입력 받기 //
    for(i=0;i<2;i++){
        printf("Enter the Name of student %d : ",i+1);
        gets(s[i].Name);
        printf("Enter the Age of student %d : ",i+1);
        scanf("%d",&s[i].Age);
        printf("Enter the Level of student %d :",i+1);
        scanf("%f",&s[i].Level);
        scanf("%c",&s[i].temp);// 버퍼 비우기 //
        printf("Enter the Grade of student %d :",i+1);
        gets(s[i].Grade);
    }
    // 포인터에 구조체 배열의 주소 할당 //
    p=&s;
    // 함수 호출 //
    show(&s);
}

실행 결과

Enter the Name of student 1 : Lucky
Enter the Age of student 1 : 27
Enter the Level of student 1 :2
Enter the Grade of student 1 :A
Enter the Name of student 2 : Pinky
Enter the Age of student 2 : 29
Enter the Level of student 2 :1
Enter the Grade of student 2 :B
The Name of student 1 is : Lucky
The Age of student 1 is : 27
The Level of student 1 is : 2.000000
The Grade of student 1 is : A
The Name of student 2 is : Pinky
The Age of student 2 is : 29
The Level of student 2 is : 1.000000
The Grade of student 2 is : B

참고 사항

위 예제에서 사용된 gets() 함수는 입력 길이를 제한할 수 없어 버퍼 오버플로우 위험이 있기 때문에 최신 C 표준(C11)에서는 제거되었습니다. 실무 환경에서는 fgets()를 사용하거나 scanf()에 폭 지정자(예: %99s)를 함께 사용하는 것이 안전합니다. 또한 구조체 포인터로 멤버에 접근할 때는 점(.) 대신 반드시 화살표 연산자(->)를 사용해야 한다는 점도 기억해 두세요.