Structure
구조체
- 다양한 data type의 data를 저장할 수 있게 하는 자료구조이다.
- C++ 에서의 구조체는 OOP의 핵심 기능인 Class의 기초이다.
- 구조체 또한 Compound data type의 일종으로 함수의 매개변수, 반호로 사용이 가능하다.
구조체의 생성 과정
1. Structure Description (구조체 서술)
- 구조체 안에 저장할 여러 가지 data type들을 서술하고 이름을 지정한다.
Ex. 구조체 선언부 예시
//Structure Description
struct inflatable {
char name[20];
float volume;
double price;
};
\(\texttt{struct}\)
- Structure identifier
- 구조체를 생성하는 키워드
\(\texttt{inflatable}\) (=\(\texttt{Tag}\))
- 구조체의 identifier (이름)
- 태그(\(\texttt{Tag}\))라고 부르기도 한다.
- \(\texttt{Tag}\)는 새로운 data type의 이름이 된다.
\(\texttt{char name[20], float volume, double price}\)
- 구조체를 구성하는 members
2. Structure Variable (구조체 변수 선언)
- 서술된 구조체에서 파생되는 구조체 변수를 생성한다.
- 구조체 서술과 구조체 변수 선언을 동시에 진행할 수 있으며 여기에 멤버 초기화까지 더불어 진행시킬 수 있다.
Example. Declaration of Structure Variable
// 구조체 변수 선언
inflatable hat;
// 구조체 변수 선언 + 초기화
inflatable tube = {
"Glorious Gloria",
1.88,
29.99
};
// ※ 일부 시스템에서 구조체 변수선언 시, 요구되는 키워드 "static"
static inflatable guest;
// 구조체 서술 + 구조체 변수 선언
struct player {
char name[20];
float speed;
double shouting;
} Jordan, Lebron;
// 구조체 서술 + 구조체 변수 선언 + 멤버 초기화
// (낮은 가독성으로 인해 권장되지 않는 방법)
struct player {
char name[20];
float speed;
double shouting;
} Jordan = {
Michael Jordan,
95.21,
89.2759
};
Ex. C++ Style vs C Style
// C++ Style
inflatable hat;
inflatable duck { // C++ 에서 "=" 는 생략이 가능하다. (List initialization)
Duck,
12.34
56.7891
};
// C Style
struct inflatable cap; // C 에서는 "struct" 키워드가 필수적이다.
struct inflatable goose = {
Goose,
43.21
13.579
};
3. Access to the Member (멤버 접근)
- Membership oprator . (comma) 를 이용해서 구조체 변수의 각 멤버에 개별적으로 접근이 가능하다.
Ex. Access to the variable member in structure variable by membership operator
inflatable hat;
hat.volume = 12.34;
cout << hat.name << std::endl;
* Memberwise assignment (멤버별 대입)
- assignment operator = (equal) 을 이용해서 한 구조체 변수에 다른 구조체 변수를 대입시킬 수 있다.
(물론, 같은 구조체 data type이라는 가정하에)
- 대입될 때는 당연히 멤버값들도 온전히 복사되어 전달된다.
Ex. Memberwise assignment for Structure object
struct inflatable {
char name[20];
float volume;
double price;
};
inflatable bouquet {
"sunflowers",
0.20,
12.49
};
inflatable choice;
choice = bouquet;
// memberwise assignment 가 진행됨
* One-time declaration
- 구조체 template 생성시, tag 이름 선언을 생략하고 구조체 변수를 선언하는 방식이다.
- 해당 구조체 template을 통해 다시 변수를 생성할 수 없다. (One-time property)
struct { // tag 이름 선언 생략
int x;
int y;
} position; // 구조체 변수 "position"
// 추후에 해당 구조체 template에 해당하는 변수를 생성할 수 없다.
4. 구조체 초기화 (C++11)
- C++11 에서는 List initialization 기능이 구조체 초기화까지 확장되었다.
- 따라서 여전히 리스트 초기화를 통한 구조체 초기화에서도 narrowing(리스트초기화의 장점)은 허용되지 않는다.
* List initialization 관련URL
- {} (중괄호)를 이용한 초기화 방법
- 모든 상황에서 사용할 수 있는 초기화 방법
- narrowing(축소)를 허용하지 않음으로써 의도하지 않은 값의 변동을 방지한다.
- auto 변수의 리스트 초기화는 바람직하지 않다.
* Arrays of Structures
- 구조체를 원소로 갖는 배열
- 각각의 원소는 구조체이므로 멤버 연산자 등 구조체 변수를 조작할 때와 방법이 크게 다르지 않다.
inflatable gifts[100]; // 구조체 변수의 선언&조작법과 크게 다를 바 없다.
cin >> gifts[0].volume;
inflatable guests[2] = { // 구조체 배열의 초기화 방법
{"Bambi", 0.5, 21.99},
{"Godzilla", 2000, 565.99}
};
gifts.price; // gifts 자체는 구조체가 아닌 배열이름이므로 아무런 의미가 없다!
* 구조체 안의 Bit Fields
- C와 마찬가지로, C++에서도 구조체 멤버들이 각각 일정 비트 수를 차지하도록 지정할 수 있다.
- Bit fields 지정은 특정 H/W 장치의 Register에 대응하는 데이터 구조를 만들 때 용이하다.
- Bti fields 를 지정할 필드 데이터형은 정수형 or 열거형 이어야 한다.
- 사용할 bit 수는 콜론(:)을 찍고 그 뒤에 적는다.
- 이름이 없는 필드를 사용하여 간격을 줄 수도 있다.
struct torgle_register {
unsigned int SN : 4; // SN 값 (4 bits)
unsigned int : 4; // 사용하지 않음(간격유지) (4bits)
bool goodIn : 1; // 유효한 입력 (1 bit)
bool goodTorgle : 1; // 토글에 성공 (1 bit)
};
// 선언 이후엔 일반적인 구조체 변수 사용방법과 다르지 않다.
torgle_register tr = {14, true, false};
if (tr.goodIn){
~~~~
}
※ 비트 필드는 저수준 프로그래밍 (임베디드 프로그래밍 등) 에서 주로 사용된다.
매개변수로써의 구조체
- C++에서는 구조체 변수는 보통의 일반 데이터형 변수처럼 함수에 값(Call by Value)으로 전달될 수 있다.
(단, C에서는 구조체를 값으로 전달하는 것을 허용하지 않는다.)
- 또한, 함수는 구조체를 리턴할 수도 있다.
- 메모리 효율 측면에서, 구조체의 주소 또는 참조를 전달하여 구조체의 내용에 직접접근하는 방식이 구조체의 크기가 큰 경우일수록 효율적이기 때문에 권고된다.
- 구조체에 대한 포인터나 참조는 일반 데이터형을 다룰 때와 다를게 없이 같은 문법을 공유한다.
(똑같이, \(texttt{*}\) 연산자와 \(\texttt{&}\) 연산자를 이용한다.)