Programming/C

C언어 - 구조체와 사용자 정의 자료형(1)

JunsuKim 2021. 10. 12.
728x90

구조체

구조체란? 하나 이상의 변수(포인터 변수와 배열 포함)를 묶어 새로운 자료형을 정의하는 도구이다.

프로그램 상에서 어떠한 사람의 정보를 저장하고 관리해야 한다 해보자.

char name[20];
char phoneNum[20];
int age;

이 세 변수는 서로 독립된 정보를 표현하는 것이 아닌, 한 사람의 정보를 표현한다.

따라서 사람이 바뀌면 그에 따른 정보를 갱신해야 하기 때문에 세 변수에 저장된 값이 동시에 갱신되어야 한다.

세 변수는 함께 있을 때 의미를 지니며, 이 중 하나가 어떠한 이유로 인해 소멸된다면 나머지 하나도 의미가 없어진다.

따라서 이 세 변수를 묶어버리는 방법이 좋은데, 이를 구조체로 정의함으로써 하나로 묶을 수 있다.

구조체는 struct 키워드를 사용하면 된다.

struct person {
    char name[20];
    char phoneNum[20];
    int age;
};

person이라는 이름의 구조체를 정의하였다.

여기서 person이라는 이름은 int, double과 같은 자료형의 이름이 된다.

이는 기본 자료형은 아니며, 기본 자료형 변수를 묶어서 새로운 자료형을 만든 것이다. 이를 "사용자 정의 자료형"이라 한다.

구조체 변수의 선언과 접근

구조체를 정의했으므로 이제는 이 자료형들을 대상으로 변수를 선언할 수 있다.

이렇게 선언된 변수를 "구조체 변수"라고 한다. 선언 방법은 다음과 같다.

struct type_name val_name;

이와 같이 구조체 변수를 선언할 때는 맨 앞에 struct 키워드를 붙이며, 이어서 구조체의 이름과 구조체 변수의 이름을 선언한다.

이를 토대로 person 구조체의 변수를 선언해보면 다음과 같다.

struct person human;

구조체 변수가 선언됬을 때 형태는 다음과 같이 존재한다.

 

그럼 구조체 변수 안에 존재하는 멤버에 접근하기 위한 기본 형식은 "구조체 변수의 이름.구조체 멤버의 이름"이다.

예를 들어 human의 멤버 age에 20을 저장하려면 다음과 같이 하면 된다.

human.age = 20;

구조체 변수의 초기화

변수를 선언과 동시에 초기화할 수 있듯이 구조체 변수도 선언과 동시에 초기화할 수 있다.

초기화 방법은 배열의 초기화 방법과 동일하다. 멤버의 순서대로 초기화할 대상을 나열하면 된다.

#include<stdio.h>

struct point {
    int xpos;
    int ypos;
};

int main() {
    struct point pos = {10, 20};
    printf("%d %d\n", pos.xpos, pos.ypos);
    return 0;
}

// 10 20

원래 구조체의 멤버에 문자열을 저장하기 위해서는 strcpy함수를 호출해야 한다. 하지만 선언과 동시에 초기화를 하면 멤버에 저장할 데이터를 단순히 나열하면 된다.

구조체 배열의 선언과 접근

int형 변수가 여러개 필요하면 int형 배열을 선언하듯이, 구조체 변수가 다수 필요하면 구조체 배열을 선언할 수 있다.

구조체 배열의 선언 방법은 일반 배열의 선언 방법과 동일하다.

/*
int형 변수: int num -> int형 배열: int arr[10]
point형(구조체) 변수 struct point pos -> point형 배열: struct point arr[10]
*/

예제를 보며 확인해보자.

#include<stdio.h>

struct point {
    int xpos;
    int ypos;
};

int main() {
    struct point arr[3];
    for (int i = 0; i < 3; i++) {
        printf("점의 좌표 입력: ");
        scanf("%d %d", &arr[i].xpos, &arr[i].ypos);
    }
    for (int i = 0; i < 3; i++) printf("[%d, %d] ", arr[i].xpos, arr[i].ypos);
    return 0;
}

구조체 배열의 초기화

구조체 변수를 선언과 동시에 초기화할 때는 중괄호를 통해 초기화할 값들을 명시했다.

따라서 구조체 배열을 선언과 동시에 초기화할 대는 배열의 길이만큼 중괄호를 이용해서 초기화를 하면 된다.

struct person arr[3] = {
    {"David", "010-1234-5678", 21},
    {"James", "010-9876-5432", 22},
    {"Nick", "010-3456-7890", 23}
};

구조체 변수와 포인터

구조체 포인터 변수의 선언 및 연산의 방법도 일반적인 포인터 변수의 선언, 연산 방법과 같다.

int형 포인터 변수를 선언하고 초기화, 접근하는 방법은 다음과 같다.

int num = 10;
int *ptr = &num;
*ptr = 20;

point형 구조체의 포인터 변수도 다음과 같이 선언, 초기화, 접근을 한다.

struct point pos = {10, 11};
struct point * ptr = &pos;
(*ptr).xpos = 20;
(*ptr).ypos = 21;

접근을 위해 포인터 변수를 대상으로 *연산을 하는 것은 동일하다. 하지만 구조체 포인터 변수의 경우 접근하고자 하는 멤버의 선택을 위해 .연산을 추가한다.

*연산과 .연산을 하나의 ->연산으로 대신할 수 있다.

ptr -> xpos = 20;
ptr -> ypos = 21;

포인터 변수를 구조체의 멤버로 선언

배열이 구조체의 멤버로 선언될 수 있듯이, 포인터 변수 또한 구조체의 멤버가 될 수 있다.

#include<stdio.h>

struct point {
    int xpos;
    int ypos;
};

struct circle {
    double radius;
    struct point* center;
};

int main() {
    struct point cen = { 2, 7 };
    double rad = 5.5;
    struct circle ring = { rad, &cen };

    printf("원의 반지름: %g\n", ring.radius);
    printf("원의 중심: [%d, %d]\n", (ring.center) -> xpos, (ring.center) -> ypos);
    return 0;
}

여기서 추가로

"TYPE형 구조체 변수의 멤버로 TYPE형 포인터 변수를 둘 수 있다"라는 것을 알아둬야 한다.

struct point {
    int xpos;
    int ypos;
    struct point *ptr;
}

 

728x90

'Programming > C' 카테고리의 다른 글

C언어 - 파일 입출력  (1) 2021.10.16
C언어 - 구조체와 사용자 정의 자료형(2)  (0) 2021.10.13
C언어 - 표준 입출력과 버퍼  (1) 2021.10.11
C언어 - 문자와 문자열 함수  (1) 2021.10.09
C언어 - 스트림(Stream)  (0) 2021.10.06

댓글