![[C언어] struct로 구조체 정의하기](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwGfl2%2FbtsakeU1Usz%2FMuHHOHBxkUQCIHU8ieLyU0%2Fimg.jpg)
구조체는 C 언어에서 서로 다른 데이터 타입을 하나로 묶어 새로운 사용자 정의 데이터 타입을 생성하는 방법이다.
정수, 문자, 실수, 포인터 등 다양한 기본 데이터 타입을 조합하여 복잡한 데이터 구조를 표현할 수 있다.
struct
정의
struct
를 정의하려면 struct
키워드 뒤에 이름과 구조체를 구성하는 다른 데이터 유형의 변수가 포함된 중괄호를 사용한다.
struct 구조체이름 {
멤버변수1의_타입 멤버변수1;
멤버변수2의_타입 멤버변수2;
...
};
예를 들어, 다음과 같이 person
이라는 구조체를 정의할 수 있다.
struct person {
char name[50]; // 이름
int age; // 나이
float height; // 키
};
위 예제에서는 세 가지 다른 데이터 유형의 변수를 정의한다. 문자 배열 name
, 정수 age
, 실수 height
를 포함하는 person
이라는 구조체라고 볼 수 있다.
구조체 멤버 액세스
구조체의 개별 멤버에 접근하기 위해서는 점(.) 연산자를 사용한다.
구조체 변수명 뒤에 점을 찍고 그 뒤에 멤버 변수명을 명시하면 된다.
struct person p1;
p1.age = 27;
p1.height = 5.8;
strcpy(p1.name, "John");
위 예제에서는 먼저 person
타입의 구조체 변수 p1
을 선언한다. 그 후 점(.) 연산자를 사용하여 각 멤버 변수에 접근하고 값을 할당한다.
age
와 height
는 단순 대입 연산자를 통해 값을 할당할 수 있다.
문자열인 name
의 경우 배열이므로 strcpy
함수를 사용해 문자열을 복사한다.
구조체 멤버 접근 시 주의할 점은 아래와 같다.
멤버 변수의 데이터 타입에 맞는 값 할당
각 멤버 변수는 선언 시 지정된 데이터 타입을 가진다.
타입에 맞지 않는 값을 할당하면 컴파일 에러가 발생하거나 예기치 않은 결과를 초래할 수 있다.
정수형 멤버에 실수나 문자열을 할당하려 하면 문제가 발생한다.
struct person p1;
p1.age = "만23살"; // Error
배열 멤버 다루기
배열 멤버의 개별 요소에 접근할 때는 인덱스를 사용한다.
structVar.arrayMember[index] = value;
전체 배열에서는 문자열과 같은 배열 전체를 다룰 때 strcpy()
나 memcpy()
등의 함수를 사용해야 한다.
단순 대입 연산자(=)로는 배열 전체를 복사할 수 없다.
구조체 포인터
구조체 포인터를 통해 멤버에 접근할 때는 화살표->
연산자를 사용한다.
구조체 포인터를 사용하면 구조체의 메모리 주소를 저장하고 구조체의 멤버에 간접적으로 접근해 수정할 수 있다.
구조체 포인터는 동적 메모리 할당, 함수 인자 전달, 연결 리스트 등의 자료구조 구현에 유용하게 사용된다.
struct person *ptr;
struct person p1;
ptr = &p1; // p1의 주소를 ptr에 할당
ptr->age = 30; // 화살표 연산자를 사용해 age 멤버에 접근 및 수정
printf("Age: %d\n", ptr->age); // 수정된 age 값 출력
이 예제에서는 person
구조체에 대한 포인터 ptr
을 선언하고, 이미 존재하는 구조체 변수 p1
의 주소를 ptr
에 할당한다.
그 후 화살표 연산자 ->
를 사용해 p1
의 멤버에 접근하고 수정한다.
구조체 포인터를 사용할 때도 주의해야 할 사항이 있다.
역참조와 멤버 접근
(*ptr).member
와 ptr->member
는 동일한 의미를 가진다. 화살표 연산자가 더 간편하고 가독성이 높으므로 화살표 연산자를 활용하면 될 것 같다.
널 포인터 검사와 메모리 관리
// 동적 메모리 할당
struct person *dynamic_ptr = (struct person *)malloc(sizeof(struct person));
if (dynamic_ptr != NULL) {
dynamic_ptr->age = 25;
strcpy(dynamic_ptr->name, "Alice");
free(dynamic_ptr); // 사용 후 메모리 해제
}
// 함수에 구조체 포인터 전달
void update_person(struct person *p) {
p->age++;
}
update_person(ptr); // 함수 호출
구조체 포인터를 사용하기 전에 널 포인터가 아닌지 확인하는 것이 안전하다.
또한 동적으로 할당된 구조체 포인터를 사용할 경우 사용이 끝난 후 반드시 메모리를 해제해야 한다.
중첩 구조체
중첩 구조체는 구조체 내부에 다른 구조체를 멤버로 포함하는 구조를 말한다.
복잡한 데이터 구조를 계층적으로 표현할 수 있고 관련 데이터를 논리적으로 그룹화할 수 있다.
struct address {
char street[50];
char city[50];
char state[50];
int zip;
};
struct person {
char name[50];
int age;
float height;
struct address addr; // 중첩된(nested) 구조체
};
이 예제에서는 address
구조체를 정의하고 person
구조체의 멤버로 포함시켰다.
address
구조체는 주소와 관련된 정보를, person
구조체는 개인 정보와 함께 주소 정보를 포함한다.
struct person p1;
strcpy(p1.name, "John Doe");
p1.age = 30;
p1.height = 175.5;
// 중첩 구조체 멤버에 접근
strcpy(p1.addr.street, "123 Main St");
strcpy(p1.addr.city, "Anytown");
strcpy(p1.addr.state, "State");
p1.addr.zip = 12345;
중첩 구조체의 멤버에 접근할 때는 점(.) 연산자를 사용한다.
'프로그래밍 언어 > C' 카테고리의 다른 글
[C언어] 문자와 문자열 (0) | 2024.07.14 |
---|---|
[C언어] union으로 공용체 정의하기 (0) | 2023.04.14 |
[C언어] typedef로 자료형 재정의하기 (0) | 2023.04.14 |
[C언어] 배열 포인터와 포인터 배열 (1) | 2023.04.14 |
[C언어] 배열 파라미터와 포인터 파라미터의 차이점 (0) | 2023.04.14 |
컴퓨터 전공 관련, 프론트엔드 개발 지식들을 공유합니다. React, Javascript를 다룰 줄 알며 요즘에는 Typescript에도 관심이 생겨 공부하고 있습니다. 서로 소통하면서 프로젝트 하는 것을 즐기며 많은 대외활동으로 개발 능력과 소프트 스킬을 다듬어나가고 있습니다.
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!