728x90

1. 구조체 개요

1) 구조체(Structure)
의미상 관계가 있는 항목을 그룹으로 묶어 표현한 자료형
- 구조체는 int, char와 같이 변수의 모양을 의미
- 차이는 int, char는 기본적으로 정해져 있는 기본 자료형이고, 
구조체는 사용자가 용도에 맞게 만들어 사용하는 사용자 자료형이다.
- 구조체를 구성하는 변수들을 멤버라고 부름

2. 구조체 정의, 선언, 사용

1) 구조체 정의
- 자료형을 정의하는 것 - 변수 선언과는 다른 개념
struct 라는 키워드를 사용
- 일반적인 구조체 정의 형식
>> 형식

struct 구조체자료형이름{
	멤버자료형 멤버변수;
	멤버자료형 멤버변수;
	...
}; // 세미콜론



>> 예시

struct student{
	int id;
	char name[8];
	double grade;
};



- 정의만 해서는 메모리에 공간이 할당되지 않음

2) 구조체 사용
- 일반적인 변수 선언과 동일한 형태
- 자료형 변수명;
- 구조체에서는 'struct 구조체자료형이름' 이 통채로 자료형을 나타냄

struct student st1, st2; // 구조체 변수 선언



변수 선언을 해야 비로소 메모리에 공간이 할당됨
- 구조체 변수 자체는 메모리 공간을 따로 가지지 않고, 멤버들의 메모리로 구성됨

3) 구조체 변수 초기화
- 다른 초기화와 유사하게 중괄호 안에 멤버 변수 순서대로 초기화 값 나열
>> 예시

struct student st1 = {10, "Tom", 3.2};



4) 멤버변수 사용
구조체 멤버 연산자 (.) 사용 : 구조체변수.멤버변수
- 비교) 구조체 변수는 멤버변수 전체를 나타냄
- 멤버변수의 자료형에  의해 사용방법이 결정됨
- int형 멤버 변수 id는 일반적인 int 변수를 사용하는 것과 동일한 방식으로 사용
>> 예시

stuct student st1, st2;
st1.id = 10;
st1.id = st1.id * 2;
printf("id: %d, st1.id);


5) 구조체 정의와 선언의 다양한 형태

(1) 자료형 정의와 변수 선언을 따로 (가장 일반적 형태)

struct student{ // 구조체 자료형 정의
	int id; char name[8]; double grade;
};

void main(){
	struct student st1; // 지역 변수 st1 선언
}



(2) 자료형 정의와 변수 선언을 동시에

struct student{ // 구조체 자료형 정의
	int id; char name[8]; double grade;
} st; // 전역 변수 st 선언
void main(){
	struct student st1; // 지역 변수 st1 선언
}



- 정의 선언과 동시에 초기화도 가능

struct student{ // 구조체 자료형 정의
	int id; char name[8]; double grade;
} st = {10, "Tom", 3.2}; // 전역 변수 st 선언 및 초기화



(3) 구조체 자료형 이름 생략 가능
- 다만, 자료형 이름이 없으므로, 다른 곳에서 선언 불가능

struct { // 구조체 자료형 정의 (이름 없음)
	int id; char name[8]; double grade;
} st; // 전역 변수 st 선언(가능)



(4) 구조체 자료형을 함수 안에서 정의
- 정의한 함수 안에서만 사용 가능

void main(){
	struct student{ // 구조체 자료형 정의 (함수 안)
		int id; char name[8]; double grade;
	};
	struct student st1; // 구조체 변수 st1 선언
}



6) 구조체에 사용 가능한 연산자
- 구조체는 사용자가 만든 자료형이기 때문에 
기본 자료형인 int, char, double 등에 비해 사용가능한 연산자가 제한적임
산술연산, 비교연산은 지원 안 됨
대입연산자(=), 주소연산자(&), 간접참조연산자(*), sizeof 연산자 등등.. 은 사용 가능

7) 구조체 변수의 대입 연산
- 모든 멤버 변수에 대해, 대입 연산이 수행됨 

>>예시

struct student st1 = {10, "Tom", 3.2};
struct student st2;
st2 = st1; // 가능



8) 구조체에 할당되는 메모리 크기
- 구조체 크기는 구조체 멤버의 크기의 합이 아닐 수도 있다
sizeof 연산자를 통해 구조체의 크기를 이용하자

3. 구조체 배열
- 구조체가 배열, 포인터, 함수등과 결합되어 확장될 수 있음

1) 구조체 배열
- 구조체가 원소로 사용된 배열
- 단, 구조체끼리의 묶음만 허용
- 선언, 접근, 초기화 등 구조체 배열에 대한 문법
- 일반 배열과 동일

2) 구조체 배열 선언과 접근: [] 사용

struct student ast[3];

ast[0].id = 10;
strcpy(ast[0].name, "Tom");
ast[0].grade = 3.2;



3) 구조체 배열 초기화 : 중괄호 {} 사용
- 생략된 부분은 0으로 초기화

int i;
struct student ast[3]
= { {10, "Tom", 3.2},
{20, "Alice"} };
// 생략된 부분은 모두 0으로 초기화



4. 구조체 포인터

1) 구조체 포인터
- 구조체 변수를 가리키는 포인터
- 구조체 변수의 시작주소가 저장
- 기본적인 사용법은 일반적인 포인터와 동일
- 다만, 구조체 포인터에서만 사용하는 표현법 존재

2) 구조체 포인터 변수 선언 및 연결
- 일반 포인터 선언과 동일: * 사용
주소연산자(&): 구조체 변수의 시작 주소
>>예시

struct student st1 = {10, "Tom", 3.2};
struct student *pst;
pst = &st1;



3) 간접 연산자(*)를 이용한 구조체 변수 접근

struct student st1 = {10, "Tom", 3.2}, st2;
struct student *pst = &st1;
st2 = *pst; // st2에 pst가 가리키는 구조체 변수를 대입



4) 간접 참조를 이용한 구조체 변수의 멤버 접근

(1) 방법 1: (*pst).id
- 포인터가 가리키는 변수에 접근하기 위해 간접연산자* 사용
- 구조체의 멤버에 접근하기 위해 멤버연산자. 사용
- *보다 .의 우선순위가 높기 때문에 괄호 반드시 필요

(2) 방법 2: pst->id
구조체 포인터에서만 사용하는 전용 연산자: ->
- 주로 이 연산자를 사용

5) 구조체 포인터 배열
- 구조체 포인터가 원소인 배열
>>예시

struct student st1 = {10, "Tom", 3.2}, st2;
struct student *past[3] = {&st1, &st2};

past[2] = past[1]; // 주소 값 대입: past[2]도 st2를 가리킴
*past[2] = *past[0]; // past[2]가 가리키는 구조체에 past[0]이 가리키는 구조체 대입



5. 구조체와 함수

1) 구조체를 함수의 인자로 사용
- 실인자의 값이 형식인자에 대입됨
- 구조체 변수라고 달라지는 건 없음
>> 예시

void print(struct student st) {
	printf("id: %d\n", st.id);
	printf("name: %s\n", st.name);
	printf("grade: %.2f\n", st.grade);
}



2) 구조체를 함수의 반환형으로 사용
- 구조체 전체 값이 통째로 호출함수에게 전달됨
>> 예시

struct student init(){
	struct student st = {0, "", 0};
	return st;
}



3) 구조체 포인터를 함수 인자로 사용
- 실인자의 값이 형식이자에 대입됨
>>예시

void init_p(struct student *pst){
	pst->id = 0;
	pst->name[0] = '\0';
	pst->grade = 0.0;
}



4) 구조체 주소를 반환하는 함수
- 일반 변수의 주소 반환과 동일
>>예시

struct student *next_addr(struct student *pst){
	return pst+1;
}



5) 함수 호출 총정리
- 함수 인자나 반환 값의 자료형에 관계없이 함수 호출 과정은 동일
- 함수 호출 시에는 전달된 값을 형식인자에 대입
- 함수 종료 시에는 리턴 값이 통째로 호출함수에 전달
- 결론: 자료형마다 따로 외우려 하지 말고 원리 이해가 중요

6. 중첩 구조체 및 자기참조 구조체

1) 중첩 구조체(nested structure)
다른 구조체가 구조체의 멤버로 사용
>>예시

struct address{ // 구조체 address 정의
	int zipcode;  char *city;
};
struct student{ // 구조체 student 정의
	int id; char name[8];  double grade;
	struct address addr; // 멤버 addr의 자료형은 struct address
};



2) 중첩 구조체 주의사항
- 자신과 동일한 구조체 자료형은 멤버로 사용될 수 없음
- 자기자신을 정의하기 위해 자기 자신이 필요함 >> 순환 오류

7. typedef 사용자형 정의

1) 사용자형 정의
- typedef문을 이용하여 자료형의 이름을 새로 정의할 수 있음

typedef int INT; // INT 자료형 정의

 

typedef struct student STUDENT; // STUDENT 형 정의



728x90

+ Recent posts