승쨩개발공부

[C++] 구조체(struct) 본문

C++

[C++] 구조체(struct)

SeungHyune 2021. 11. 26. 00:05

구조체

사용자 정의 자료형

-> 사용자가 자료형을 만들어서 사용하는 것.

-> 단, 몇 바이트 자료형인지 어떤 형식으로 읽을 것인지는 설정할 수 없다.

 

데이터 덩어리, 데이터 집합

->필요한 변수들을 하나로 묶어 놓은 것.

 

구조체 정의

컴파일러에게 이러한 자료형을 만들어서 사용하겠다 알려주는 것.

 

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