🎯 구조체
배열이 하나의 타입을 같은 이름으로 여러개 만들어서 사용한다면,
구조체는 여러 타입의 변수들을 하나로 모아서 사용할 수 있게 해주는 기능입니다.
struct 구조체이름
{
변수선언
}
- 구조체 이름 : 관련 있는 이름으로 작성하거나 사용하는 목적에 맞는 이름을 사용합니다.
- 변수 : 다양한 타입의 변수들을 선언할 수 있습니다.
- 언리얼에서 사용시 구조체 이름 앞에 대문자F를 붙여줍니다 ( ex: Fitem)
▶️ 구조체 선언과 사용
// 구조체
struct FItem
{
char name[32] = {};
int option = 0;
int price = 0;
}
int main()
{
// 구조체 사용
FItem item;
// strcpy_s : 문자열 복사 함수. 오른쪽의 문자열을 왼쪽의 문자 배열에 복사해주는기능.
strcpy_s( item.name, "목검" );
item.option = 1;
item.price = 1000;
return 0;
}
- 구조체변수. 을 이용하여 구조체의 멤버에 접근이 가능합니다.
- 구조체는 기본 접근한정자가 public 입니다.
▶️ 구조체의 활용
- 구조체도 배열을 이용해 사용할 수 있습니다.
- 구조체 초기화도 가능합니다.
// 구조체타입 변수하나 만들어짐
// 구조체도 초기화 가능 = {};
// 전부 0으로 초기화
Fitem item = {};
// 선언과 동시에 값 넣기 가능
// 넣지 않은 값은 0으로 초기화
Fitem item2 = { "철검", EitemType::Weapon };
// 구조체도 배열 선언 가능.
Fitem itemArr[10];
▶️ 구조체 크기 확인하기 ⭐ ⭐ ⭐ ⭐ ⭐
구조체 사이즈는 정확히 계산할 줄 알아야합니다! 면접 단골 질문!
✔️ 예제1
enum class EItemType : unsigned char
{
weapon,
armor,
}
struct Fitem
{
// 문자열 사용시 문자열 배열의 끝은 0 (null문자)로 저장되어야 한다.
char Name[32]; // 32바이트
EItemType ItemType; // 1
// bool test => 추가해도 동일하게 41바이트.
int Option; // 4
// bool test2 => 추가시 48바이트
int Price; // 4
// 41바이트가 나와야 하는데, 총 44바이트가 나오고 있음
};
int main()
{
FItem item = {};
std::cout << sizeof(FItem) << std::endl; // 44 출력
return 0;
}
- name : 32바이트
- ItemType : 1바이트
- option : 4바이트
- price : 4바이트
=> 32 + 1 + 4 + 4 = 41인데 44가 출력됩니다 ( x64, 구조체 멤버맞춤 기본값 기준 )
- 컴파일러가 구조체의 최적화를 위해 구조체 멤버맞춤을 합니다.
- 4바이트 단위로 공간을 만들어서 변수들을 넣어줍니다
- 4바이트로 만드는 이유 : 기본 구조체 멤버맞춤 기본값일 경우, 제일 큰 변수의 크기 (FItem에서는int)가 4byte에 맞춰서 만들어지기 때문입니다.
- 바이트 정렬(Byte Aligment) : 자료형의 크기와 메모리상의 위치를 정렬하는것을 뜻합니다. 위 예시에선 제일 큰 변수인 int형 4byte의 크기에 맞춰서 바이트 정렬이 이뤄지는것을 확인하실 수 있습니다.
- 바이트 패딩 (Byte Padding) : 바이트 정렬을 위해 추가될 수 있는 빈(남는) 공간입니다. 위 예시에선 EItemType의 크기는 1바이트이지만 남는 3바이트의 패딩이 생겼음을 알 수 있습니다.
- 바이트 정렬과 바이트 패딩은 자료형의 크기와 메모리상의 위치를 정렬하기 위해 사용됩니다. 이는 cpu의 메모리 접근 시간과 효율성을 개선하기 위한 것입니다.
- 4바이트로 만드는 이유 : 기본 구조체 멤버맞춤 기본값일 경우, 제일 큰 변수의 크기 (FItem에서는int)가 4byte에 맞춰서 만들어지기 때문입니다.
| 4byte*8 = 32byte : name + 남는공간 0 |
+ | 4byte : ItemType 1byte + 남는공간 3byte |
+ | 4byte : option + 남는공간 0 |
+ | 4byte : price + 남는공간 0 |
✔️ 예제 2 - 바이트정렬 ( 멤버맞춤 )의 기준 : 가장 큰 멤버 변수의 크기
enum EItemType : unsigned char
{
weapon,
armor,
};
struct FItem
{
EItemType itemType;
};
int main()
{
// 구조체 사용
FItem item;
std::cout << sizeof( FItem ) << std::endl;
return 0;
}
FItem에서 제일 큰 변수의 크기가 1byte이기 때문에 1이 출력됩니다.
struct FItem
{
EItemType itemType;
char name[32] = {};
int option = 0;
int price = 0;
__int64 big = 0;
};
- 가장 큰 변수타입인 __int64 타입에 맞춰 8byte 단위로 구조체 멤버맞춤이 되며
구조체의 크기는 총 56바이트가 됩니다.
✔️ 예제 3 - 빈 구조체
- 빈 클래스 or 빈 구조체 : 크기 출력시 1바이트가 나옵니다.
- 1바이트인 이유 : c++에서는 크기가 0인 독립 구조의 객체가 생기는것을 금지합니다. 메모리에 변수 선언하기 위한 최소 변수 단위로 공간을 미리 비워둡니다. 메모리에 할당하기 위한 최소 변수 단위로 맞춰집니다.
- 클래스도 동일합니다. 대신 클래스는 빈 클래스를 상속받을 경우에 예외가 발생하는데, 공백 클래스를 상속받을 경우 공백클래스의 크기는 0이 잡힙니다. 단일상속에만 적용됩니다.
- 아무런 데이터를 저장하고 있지 않은 클래스의 의무적으로 할당되는 메모리를 절약하기 위해 사용하는 방법을 EBO(Empty Base Optimization), "공백 기본 클래스 최적화" 라고 합니다.
- EBO를 적용한 CChild 클래스는 빈 클래스를 상속받았지만 변수 num의 int크기인 4바이트의 크기만 할당되는것을 확인하실 수 있습니다.
✔️ 예제 4 - 배열이어도 변수의 크기에 맞춰집니다.
struct fTest1
{
char name[32];
char text ;
};
- 33바이트. char(1byte)에 맞춰서 멤버맞춤이 1바이트가 되기 때문입니다.
✔️ 예제 5 - 구조체 크기 최적화
struct FItem
{
EItemType itemType;
int option = 0;
bool isActive = true;
};
+ | 4byte : ItemType 1byte + 남는공간 3byte |
+ | 4byte : option 4byte + 남는공간 0 |
+ | 4byte : isActive 1byte + 남는공간 3byte |
위 구조에선 변수 선언 순서대로 메모리 할당이 일어나기 때문에
실질적으론 6byte만(패딩까지 8byte) 필요하지만, 총 12byte를 사용하고 있습니다.
struct FItem
{
EItemType itemType;
bool isActive = true;
int option = 0;
};
위처럼 변수 생성 위치를 변경하여 메모리를 효율적으로 사용할 수 있습니다.
✔️ 예제 6 - 구조체 정렬 바이트의 기준
struct FA
{
int a;
int b;
};
struct FB
{
FA structA;
int b;
};
위 예시에서 FA는 맞춤 4바이트, 총 크기가 8바이트입니다
FB는 제일 큰 멤버인 FA의 크기가 8바이트임에도 불구하고 맞춤이 4바이트, 총 크기가 12바이트가 나오고 있습니다.
정렬 바이트(멤버맞춤)의 크기는 무조건 제일 큰 멤버가 아님을 알 수 있습니다.
✔️ 예제 6-2 - 구조체 정렬 바이트의 기준
struct FA
{
int a;
int b;
__int64 big;
};
struct FB
{
FA structA;
int b;
};
예제 6에서 FA의 멤버변수로 __int64 타입의 big 변수가 추가되었습니다.
FB의 맞춤은 8바이트로
정렬 바이트(멤버맞춤)의 기준은 가장 큰 멤버의 크기가 아닌 가장 큰 멤버 변수임을 알 수 있습니다.
▶️ 출력하지 않고 구조체, 클래스 크기 확인하기
visual studio 에서 std::cout 을 출력하지 않고도 구조체와 클래스의 크기가 확인 가능합니다.
확인하고자 하는 구조체의 이름에 마우스 커서를 가져다대면
구조체의 크기를와 멤버맞춤 사이즈 확인하실 수 있습니다.
▶️ Visual Studio에서 구조체 멤버맞춤 옵션 확인하기
프로젝트 오른쪽마우스 -> 속성
C/C++ - 코드생성 - 구조체 멤버맞춤
▶️ 구조체 멤버맞춤 관련 참고사항
- 나중에 서버 구조체 멤버맞춤이 1바이트고, 클라는 구조체 멤버맞춤이 4바이트일 경우, 맞지가 않아서 에러나는 경우가 있다고 합니다. 서버와 클라는 맞춰야 합니다.
- 클래스도 동일한 기준 입니다.
'개발개발 > c++' 카테고리의 다른 글
c++의 include define, extern, memcpy_s (0) | 2024.12.09 |
---|---|
c++의 지역변수, 전역변수, 메모리 영역, static 변수, 동적할당, 함수 오버로딩, 함수의 디폴트 인자 (0) | 2024.12.08 |
c++의 함수 (0) | 2024.12.06 |
c++의 조건문, 난수, 사용자 정의 변수타입, enum class, 반복문, 배열 (1) | 2024.12.05 |
c++의 구조, 문자열 출력, 변수, 상수, 형변환 (0) | 2024.12.04 |
댓글