Notice
Recent Posts
Recent Comments
Link
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Tags more
Archives
Today
Total
관리 메뉴

냥집사의 개발일지

C언어 - 구조체 (struct) (2) 본문

C언어

C언어 - 구조체 (struct) (2)

깅햄찌 2022. 9. 24. 13:45
반응형

안녕하세요 저번 포스팅에 이어 구조체에 대해 더 정리해보겠습니다. 

구조체의 활용 예제를 몇 가지 살펴볼 텐데요.

1. 배열 및 포인터를 구조체의 멤버 변수로 사용

2. 구조체를 구조체의 멤버 변수로 사용

 

 

1. 배열 및 포인터를 구조체의 멤버 변수로 사용

아래 예제는 이름을 배열로, 자기 소개말은 포인터로 구조체의 멤버 변수를 구성했습니다. 

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

struct profile{
    char name[10]; 
    int age;
    char *introduction;
};

int main(){
    struct profile me;

    strcpy(me.name, "Jeff");
    me.age = 20;
    me.introduction = (char *)malloc(100 * sizeof(char));
    printf("input the introduction : ");
    gets(me.introduction);

    printf("name           : %s\n", me.name);
    printf("age            : %d\n", me.age);
    printf("introduction   : %s\n", me.introduction);

    free(me.introduction);

    return 0;
}

1. me라는 profile 구조체의 변수를 선언합니다. 

2.strcpy란 문자열 복사 함수를 이용하여 name배열에 문자열을 복사합니다. 

   // strcpy(복사될 문자열, 복사할 문자열); (strcpy는 복사될 문자열의 포인터를 반환합니다.)

3. introduction 포인터에 100byte 동적 할당된 메모리를 가리키게 합니다.

4. gets 함수로 문자열을 입력받고 introduction 포인터에 할당합니다. 

5. 아래 결과처럼 구조체 멤버 변수를 이용해 원하는 결과를 출력한 것을 확인 할 수 있습니다. 

 

2. 구조체를 구조체의 멤버 변수로 사용

profile 구조체 안에 region 구조체가 멤버 변수로 있습니다.

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

struct region{
    char city [20];
    char *district;
};

struct profile{
    char name[10]; 
    int age;
    struct region re;
    char *introduction;
};



int main(){
    struct region re = {"Seoul", "Hongdae"};
    struct profile me = {"Jeff", 20, re,"hello_world"};
    struct profile you;

    you = me;

    printf("name           : %s\n", you.name);
    printf("age            : %d\n", you.age);
    printf("city           : %s\n", you.re.city);
    printf("district       : %s\n", you.re.district);
    printf("introduction   : %s\n", you.introduction);

    return 0;
}

1. 구조체는 구조체와 직접 대입이 가능합니다. (you = me)

2. 구조체 안에 구조체는 멤버 접근 연산자를 이용하여 접근할 수 있습니다. (you.re.city)

3. 아래 결과 처럼 출력하고자 하는 값이 출력되었음을 확인할 수 있습니다. 

 

Tips 구조체는 구조체를 구조체에 복사할 수 있습니다.

         다만, 주의해야 할 점은 구조체 멤버 변수 중 포인터 변수가 있다면

         구조체 복사 시 얕은 복사가 되어 2개의 구조체 변수에서 같은 멤버 변수에 접근할 수 있는 문제가 발생합니다. 

         이와 같은 문제를 방지하기 위해 구조체를 복사한 뒤 포인터 멤버 변수만 따로 원본의 data를 복사하면 됩니다!

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


struct profile{
    char name[10]; 
    int age;
    char *introduction;
};



int main(){
    struct profile me = {"Jeff", 20, NULL};
    me.introduction = (char *)malloc(100 * sizeof(char));
    struct profile you;
    
    strcpy(me.introduction, "hello_Jeff");
    you = me;
    strcpy(me.introduction, "hello_Alana");

    printf("name           : %s\n", you.name);
    printf("age            : %d\n", you.age);
    printf("introduction   : %s\n", you.introduction);

    free(me.introduction);
    free(you.introduction);

    return 0;
}

you에 me를 대입한 뒤 me의 introduction에 "hello_Alana" 문자열을 대입했는데 

아래 결과를 보니 you의 introduction이 수정된 것을 확인할 수 있습니다. 

이는 me&you의 introduction 포인터가 같은 주소를 가리키고 있기 때문입니다. (얕은 복사)

또한 같은 주소가 이중으로 free 되는 문제가 발생합니다. 

free가 이중으로 될 시 process는 종료됩니다!! 

아래 예제에서는 you의 introduction을 동적 할당해주고 me의 introduction의 data를 strcpy로 복사하였습니다. (깊은 복사)

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


struct profile{
    char name[10]; 
    int age;
    char *introduction;
};



int main(){
    struct profile me = {"Jeff", 20, NULL};
    me.introduction = (char *)malloc(100 * sizeof(char));
    struct profile you;
    
    strcpy(me.introduction, "hello_Jeff");
    you = me;
    you.introduction = (char *)malloc(strlen(me.introduction) + 1);
    strcpy(you.introduction, me.introduction);
    strcpy(me.introduction, "hello_Alana");

    printf("name           : %s\n", you.name);
    printf("age            : %d\n", you.age);
    printf("introduction   : %s\n", you.introduction);

    free(me.introduction);
    free(you.introduction);

    return 0;
}

아래 결과처럼 me의 introduction이 you의 introduction에 영향을 주지 않고 독립적이라는 것을 확인할 수 있습니다. 

 

저번 포스팅에 이어 구조체에 대해  정리해보았습니다. 

구조체 멤버 변수로 배열, 포인터, 구조체를 선언하는 방법, 구조체에 구조체를 복사할 때 주의점 등

을 알아보았는데요. 이번 포스팅이 구조체를 이해하는데 많은 도움이 되었으면 좋겠습니다~

다음 포스팅에서 만나요~

Comments