승쨩개발공부
[C++] 구조체(struct) 본문
구조체
사용자 정의 자료형
-> 사용자가 자료형을 만들어서 사용하는 것.
-> 단, 몇 바이트 자료형인지 어떤 형식으로 읽을 것인지는 설정할 수 없다.
데이터 덩어리, 데이터 집합
->필요한 변수들을 하나로 묶어 놓은 것.
구조체 정의
컴파일러에게 이러한 자료형을 만들어서 사용하겠다 알려주는 것.
struct 자료형이름
{
멤버 변수 선언;
멤버 변수 선언;
}
->
// 구조체 정의
struct tagGrade
{
char szName[20];
int iKor;
int iEng;
int iMath;
int iTotal;
float fAver;
int point;
};
구조체 초기화
배열과 비슷한 형태를 가진다.
1. 쓰래기 값 초기화
struct tagGrade tGrade;
2. 모든 멤버 변수 0으로 초기화
struct tagGrade tGrade = {};
3. 선언한 순서대로 값 입력
struct tagGrade tGrade = { "AAA", 10, 20, 30 };
멤버 접근
구조체에서 멤버에 접근하는 방법은 연산자를 사용한다
.(dot) 연산자
.(dot) 연산자 기준 좌측에는 구조체를 명시하고,
.(dot) 연산자 기준 우측에는 멤버 변수를 명시한다.
-> 이 경우 명시한 멤버 변수에 접근하여 값을 읽거나 쓸 수 있다.
struct tagGrade tGrade = { "AAA", 10, 20, 30 };
tGrade.iTotal = tGrade.iKor + tGrade.iEng + tGrade.iMath;
tGrade.fAver = tGrade.iTotal / 3.f;
tGrade.szName = "BBB"; // 불가능
strcpy_s(tGrade.szName, 20, "BBB");
cout << "이름: " << tGrade.szName << endl;
cout << "국어: " << tGrade.iKor << endl;
cout << "영어: " << tGrade.iEng << endl;
cout << "수학: " << tGrade.iMath << endl;
cout << "총점: " << tGrade.iTotal << endl;
cout << "평균: " << tGrade.fAver << endl;
typedef
자료형에 새로운 별명을 부여하는것.
typedef struct tagGrade
{
char szName[20];
int iKor;
int iEng;
int iMath;
int iTotal;
float fAver;
int point;
}GRADE;
typedef 을 사용하기 전
struct tagGrade tGrade = { "AAA", 10, 20, 30 };
typedef 을 사용한 후
GRADE tGrade = { "AAA", 10, 20, 30 };
-> 자료형의 길이를 줄일수 있다.
C구조체와 C++구조체의 차이점
typedef 유무
-> C++ 구조체의 struct는 typedef을 내부적으로 가지고 있다!
C구조체
struct tagGrade tGrade;
C++구조체
tagGrade tGrade;
구조체의 포인터형
구조체를 메모리에 등록 시킨 것.
GRADE tGrade;
구조체의 주소를 저장할 공간을 메모리에 등록 시킨 것.
GRADE* pGrade;
->
GRADE tGrade = { "AAA", 10, 20, 30 };
GRADE* pGrade = &tGrade;
.(dot) 연산자 기준 좌측에는 구조체가 있어야하지만
구조체 대신 주소가 존재해 *(역참조 연산자) 를 붙여줘야 한다.
(*pGrade).szName;
구조체 포인터의 멤버 접근
-> : 화살표 연산자(멤버 접근 포인터 연산자)
매번 (*)역참조 연산자를 붙이고 .(dot) 연산자를 쓰기엔 불편함이 있다
-> 화살표 연산자를 사용하면 좀더 편하고 빠르게 코드를 작성할 수 있다.
pGrade->szName;
pGrade->iTotal = pGrade->iKor + pGrade->iEng + pGrade->iMath;
pGrade->fAver = pGrade->iTotal / 3.f;
cout << "이름: " << pGrade->szName << endl;
cout << "국어: " << pGrade->iKor << endl;
cout << "영어: " << pGrade->iEng << endl;
cout << "수학: " << pGrade->iMath << endl;
cout << "총점: " << pGrade->iTotal << endl;
cout << "평균: " << pGrade->fAver << endl;
주의 사항
구조체 포인터형을 선언 후 초기화하지 않고 멤버에 접근할 경우 문제가 발생할 수 있다.
GRADE* pGrade = nullptr;
pGrade->szName;
pGrade->iKor = 100;
pGrade->iEng;
구조체 멤버로 자기 자신을 가지는 방법
자기 자신을 멤버로 가질 경우에는 포인터 형을 사용해야한다.
typedef struct tagNode
{
char chNode;
int iNode;
float fNode;
double dNode;
자기 자신을 멤버로 가질 경우에는 포인터 형을 사용해야한다.
tagNode* pNode;
구조체의 크기를 계산하려 했더니 구조체가 멤버로 포함되어있다.
크기를 구하기 위해 멤버 구조체를 펼친다.
그랬더니 또 구조체가 있다!
-> 무한 반복
구조체의 크기를 계산할 수 없는 문제가 발생한다.
tagNode tNode; // 불가능
자기 자신을 멤버로 가질 경우에는 typedef으로 재정의된 이름말고,
본연의 이름을 사용해야한다.
NODE tNode; // 컴파일 오류
}NODE;
구조체의 크기
1. 멤버 변수들을 모두 확인한다.
2. 멤버 변수 중 크기가 가장 큰 변수를 기준으로 설정한다.
3. 기준 만큼 메모리를 할당한다.
5. 할당한 메모리에 선언한 순서대로 멤버들을 채워 넣는다.
6. 모든 멤버를 다 채워 넣을 경우 할당된 메모리가 최종 크기가 된다.
typedef struct tagSize
{
char chSize; // 1
int iSize; // 4
float fSize; // 4
double dSize; // 8
}SIZE;
->
가장 큰 변수 double(8Bytes)
필요한 메모리 크기 : 17bytes
double(8Bytes) * 2 = 16Bytes
1Bytes가 부족해도 기준인 8Bytes를 늘리게되어 최종 크기가 24Bytes가 된다.
cout << "sizeof(SIZE): " << sizeof(SIZE) << endl; // 24
이 남은 7Bytes의 빈 공간의 크기를 byte padding(바이트 패딩)이라고 부른다.
바이트 패딩
구조체의 크기를 설정하다보면 빈 공간이 생기게 된다.
이러한 빈 공간을 byte padding(바이트 패딩)이라고 부른다.
바이트 패딩은 더 이상 사용하지 않는 메모리 공간이 된다.
바이트 패딩을 최소화시키는 방법
1. 문자 배열
2의 n승으로 선언하자.
2. 작은 크기부터 큰 크기 순서대로 선언하자.
구조체 멤버로 구조체가 있을 경우 크기
1. 구조체를 모두 펼친다.
2. 멤버 구조체 또한 펼친다.
3. 모두 펼친 후 크기가 가장 큰 자료형을 기준으로 설정한다.
4. 기준을 토대로 각 구조체의 크기를 각각 계산한다.
5. 이후, 두 크기를 합산한 결과가 최종 크기가된다.
typedef struct tagSize
{
char chSize; // 1
int iSize; // 4
float fSize; // 4
double dSize; // 8
}SIZE; // 24
typedef struct tagSize2
{
short nSize2; // 2
int iSize2; // 4
long long llSize2; // 8
SIZE tSize;
}SIZE2; // 16
두 구조체 모두 8Bytes가 가장크다.
8Bytes를 기준으로 잡게된다.
16 + 24 = 40
cout << "sizeof(SIZE2): " << sizeof(SIZE2) << endl; // 40
'C++' 카테고리의 다른 글
[C++] 동적할당 (0) | 2021.11.29 |
---|---|
[C++] Text RPG (0) | 2021.11.26 |
[C++] 문자열 함수 / 메모리 함수 (0) | 2021.11.25 |
[C++] 배열 (0) | 2021.11.24 |
[C++] 포인터 / const포인터 (0) | 2021.11.24 |