구조체는 "각 원소의 타입이 제각각인 배열"이다.
구조체에서는 구성 요소를 멤버라고 부르며, 구조체는 정의할 때 모든 원소의 타입을 명시해 주어야 한다.
구조체의 구조는 다음과 같다.
struct 구조체_이름 {
자료형 멤버_이름;
};
/* 구조체의 도입 */
#define _CRT_SECURE_NO_WARNINGS // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h>
struct Person { // 구조체 정의
char name[20]; // 구조체 멤버 1
int age; // 구조체 멤버 2
char address[100]; // 구조체 멤버 3
};
int main() {
struct Person person1; // 구조체 변수 선언
// 점으로 구조체 멤버에 접근하여 값 할당
strcpy(person1.name, "홍길동");
person1.age = 30;
strcpy(person1.address, "서울시 용산구 한남동");
// 점으로 구조체 멤버에 접근하여 값 출력
printf("이름: %s \n", person1.name);
printf("나이: %d \n", person1.age);
printf("주소: %s \n", person1.address);
return 0;
}
struct Person { // 구조체 정의
char name[20]; // 구조체 멤버 1
int age; // 구조체 멤버 2
char address[100]; // 구조체 멤버 3
} person1; // 구조체를 정의하는 동시에 변수 person1 선언
위와 같은 방법을 통해 main() 함수 밖에서 변수를 정의하여 전역 변수로 선언할 수 있다.
struct 구조체_이름 변수_이름 = {.멤버_이름1 = 값1, .멤버_이름2 = 값2};
struct 구조체_이름 변수_이름 = {값1, 값2};
위와 같은 방법을 통해 구조체 변수를 선언하는 동시에 초기화할 수 있다.
#include <stdio.h>
struct Person {
char name[20];
int age;
char address[100];
};
int main() {
struct Person person1 = {.name = "홍길동", .age = 30, .address = "서울시 용산구 한남동"};
printf("이름: %s \n", person1.name);
printf("나이: %d \n", person1.age);
printf("주소: %s \n", person1.address);
struct Person person2 = {"고길동", 40, "서울시 서초구 반포동"};
printf("이름: %s \n", person2.name);
printf("나이: %d \n", person2.age);
printf("주소: %s \n", person2.address);
return 0;
}
typedef를 이용하여 struct 키워드 없이 구조체를 선언할 수 있다.
typedef struct 구조체_이름 {
자료형 멤버_이름;
} 구조체_별칭;
typedef는 구조체 뿐만 아니라 모든 자료형의 별칭을 만들 수 있다.
typedef int myint; // int를 별칭 myint로 정의
typedef int *pmyint; // int 포인터를 별칭 pmyint로 정의
myint num1; // myint로 변수 선언
pmyint numptr1; // pmyint로 포인터 변수 선언
numptr1 = &num1; // 포인터에 변수의 주소값 저장
struct 뒤에 붙는 구조체 이름은 원래 구조체 태그라고 부른다. typedef로 정의한 구조체 별칭은 사용자 정의 타입의 이름으로 부를 수 있다.
구조체는 여러 멤버 변수가 들어있어서 크기가 큰 편이기 때문에 구조체 변수를 일일이 선언해서 사용하는 것보다 포인터에 메모리를 할당해서 사용하는 것이 효율적이다. main 함수가 아닌 함수를 만들어서 구조체를 사용할 때 구조체 포인터를 자주 활용하게 된다. 다른 자료형과 마찬가지로 구조체도 포인터를 선언할 수 있으며 구조체 포인터에는 malloc 함수를 사용하여 동적 메모리 할당할 수 있다.
struct 구조체_이름 *포인터_이름 = malloc(sizeof(struct 구조체_이름));
#define _CRT_SECURE_NO_WARNINGS // 컴파일 에러 방지
#include <stdio.h>
#include <string.h> // strcpy 함수가 선언된 헤더 파일
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일
struct Person {
char name[20];
int age;
char address[100];
};
int main() {
// 구조체 포인터 선언, 동적 메모리 할당
struct Person *person1 = malloc(sizeof(struct Person));
// 화살표 연산자로 구조체 멤버에 접근하여 값 할당
strcpy(person1 -> name, "홍길동");
person1 -> age = 30;
strcpy(person1 -> address, "서울시 용산구 한남동");
// 화살표 연산자로 구조체 멤버에 접근하여 값 출력
printf("이름: %s \n", person1 -> name);
printf("나이: %d \n", person1 -> age);
printf("주소: %s \n", person1 -> address);
// 동적 메모리 해제
free(person1);
return 0;
}