이번에는 구조체 자료형으로도 배열을 만들 수 있다는 사실과 구조체 변수의 주소값을 포인터변수에 저장할 수 있다는 사실을 보여드리겠습니다.

먼저 우리가 구조체를 정의하고 거기에 따라 여러사람의 정보를 담는다고 해봅시다. 10명의 정보를 저장하려면 구조체변수를 10개, 100명의 정보를 저장하려면 구조체변수를 100개 선언해야하겠죠. 하지만 그 수가 커질수록 이는 번거로운 작업이 될 것입니다. 이 때에 간단하게 길이가 10이나 100인 구조체 자료형의 배열을 선언하고 거기에 구조체변수를 저장하면 됩니다.

#include <stdio.h>

void clear(void) //입력버퍼에서 "\n" 비우기 함수 
{
    while(getchar()!="\n")
    {

    }
}

struct person
{
    char name[10];
    int age;
    char blood_type;
}

int main(void)
{
    struct person arr[3];
    int i=0;

    // 입력 받기
    for(int i=0; i<3; i++)
    {
        printf("arr[%d] age : ", i);
        scanf("%d", &(arr[i].age));
        clear();

        printf("arr[%d] blood_type : ", i);
        scanf("%c", &(arr[i].blood_type));
        clear();
    }

    printf("\n");

    // 배열 정보 출력
    for(int i=0; i<3; i++)
    {
        printf("arr[%d] name : %2s, age : %2d, blood_type : %2c\n", i, arr[i].name, arr[i].age, arr[i].blood_type);
    }

    return 0;
}

실행결과

arr[0] name : John

arr[0] age : 20

arr[0] blood_type : A

arr[1] name : Harry

arr[1] age : 40

arr[1] blood_type : B

arr[2] name : Victor

arr[2] age : 50

arr[2] blood_type : O

arr[0] name : John, age : 20, blood_type : A

arr[1] name : Harry, age : 40, blood_type : B

arr[2] name : Victor, age : 50, blood_type : O

계속하려면 아무 키나 누르십시오 . . .

구조체 타입의 배열을 선언하고 데이터를 저장해봤습니다. int형 배열이 원소로 int형 변수들을 가지는것처럼 구조체로 정의한 person타입의 배열은 person타입의 변수들을 원소로 가집니다.

초기화 역시 배열의 선언과 동시에 할 수 있습니다.

#include <stdio.h>

struct person
{
    char name[10];
    int age;
    char blood_type;
}

int main(void)
{
    struct person arr[3] = {\{"John", 20, 'A'}, {"Harry", 41, 'B'}, {"Keynn", 32, 'O'}\};

    int i=0;

    for(int i=0; i<3; i++)
    {
            printf("arr[%d] name : %2s, age : %2d, blood_type : %2c\n", i, arr[i].name, arr[i].age, arr[i].blood_type);
    }

    return 0;
}

실행결과

arr[0] name : John, age : 20, blood_type : A

arr[1] name : Harry, age : 41, blood_type : B

arr[2] name : Keynn, age : 32, blood_type : O

계속하려면 아무 키나 누르십시오 . . .

구조체 타입의 배열도 기본자료형의 배열들과 별반 다르지 않습니다.

그리고 우리는 포인터를 선언할 때 int형, double형처럼 포인터형을 지정해주었고 이 포인터형이라는것은 포인터가 가르키는 변수의 자료형이고 포인터연산을 할 때 참조할 메모리공간의 크기를 알려주는 역할을 한다 했습니다. 구조체형의 포인터 역시 같습니다.

#include <stdio.h>

struct person
{
    char name[10];
    int age;
    char blood_type;
}

int main(void)
{
    struct person per1 = {"John", 20, 'B'};
    struct person per2 = {"Kelly", 41, 'A'};

    struct person *ptr1 = &per1;
    struct person *ptr2 = &per2;

    printf("%s %d %c\n", (*ptr1).name, (*ptr1).age, (*ptr1).blood_type);
    printf("%s %d %c\n", (*ptr2).name, (*ptr2).age, (*ptr2).blood_type);

    return 0;
}

실행결과

John 20 B

Kelly 41 A

계속하려면 아무 키나 누르십시오…

구조체의 멤버 역시 일반 변수처럼 포인터의 * 연산자를 사용해서 접근도 가능하고 데이터의 저장도 가능하다는 사실을 확인했습니다. 그리고 구조체형의 포인터변수를 다룰때에는 * 연산자와 . 연산자를 합쳐서 -> 연산자로 바꿔쓸 수 있습니다.

#include <stdio.h>

struct person
{
    char name[10];
    int age;
    char blood_type;
}

int main(void)
{
    struct person per1 = {"John", 20, 'B'};
    struct person per2 = {"Kelly", 41, 'A'};

    struct person *ptr1 = &per1;
    struct person *ptr2 = &per2;

    printf("%s %d %c\n", ptr1->name, ptr1->age, ptr1->blood_type);
    printf("%s %d %c\n", ptr2->name, ptr2->age, ptr2->blood_type);

    return 0;
}

실행결과

John 20 B

Kelly 41 A

계속하려면 아무 키나 누르십시오…

실행결과는 같습니다.

포인터변수가 구조체의 멤버로 선언될 수도 있습니다.

#include <stdio.h>

struct nums
{
    int * a;
    int * b;
};

int main(void)
{
    int num1 = 10;
    int num2 = 20;

    struct nums myNums = {&num1, &num2};

    printf("%d %d\n", *(myNums.a), *(myNums.b));

    return 0;
}

실행결과

계속하려면 아무 키나 누르십시오…

구조체의 멤버인 포인터 변수에 num1과 num2의 주소값을 저장하고 *와 . 연산자를 사용해서 데이터에 접근했습니다. 이정도쯤 되면 구조체가 기본 자료형과 별반 다르지 않은 하나의 자료형이라는 것을 알 수 있습니다.

한 가지 중요한 사실이 하나 더 있습니다. 배열의 주소는 배열의 첫 번째 원소의 주소와 동일한 것 처럼, 구조체 변수의 주소값은 구조체 변수의 첫 번째 멤버의 주소와 동일하다는 사실입니다. 이를 확인하기 위해 다음 코드를 봅시다.

#include <stdio.h>

struct nums
{
    int a;
    int b;
    struct nums * c;
}

int main(void)
{
    struct nums myNums;
    myNums.a = 10;
    myNums.b = 20;
    myNums.c = &myNums;

    printf("%d %d %d\n", myNums.a, myNums.b, *(myNums.c));

    return 0;
}

실행결과

10 20 10

계속하려면 아무 키나 누르십시오…

구조체를 가르키는 포인터 변수로 메모리에서 데이터를 읽었는데 10이 나왔습니다. 즉, 구조체를 가르키는 포인터 변수가 a를 가르킨다는 겁니다.

결론 : 구조체 변수의 주소값은 구조체 변수의 첫 번째 멤버의 주소값이다.

'프로그래밍 언어 > C' 카테고리의 다른 글

(C언어) 41 - 구조체의 함수 전달  (0) 2020.05.14
(C언어) 40 - typedef 선언  (0) 2020.05.14
(C언어) 38 - 구조체(1)  (0) 2020.05.14
(C언어) 37 - 버퍼(Buffer)  (0) 2020.05.14
(C언어) 36 - string  (0) 2020.05.14

+ Recent posts