[Rookiss C++] 구조체

황교선·2023년 3월 20일
0

cpp

목록 보기
10/19

하나의 변수 안에 여러 개의 데이터를 관리할 수 있는 방법이 여러 가지가 있다. 아직 배열을 배우진 않았지만, 같은 자료형 변수를 연속적으로 할당할 수 있는 배열과 여러가지의 자료형의 변수들을 하나의 자료형으로 만드는 구조체이다.

예를들어 학생에 대한 여러가지 정보를 관리하고 싶다고하자. 학생의 이름, 학생의 반, 학생의 번호, 학생의 키와 몸무게에 대해서 다음과 같이 코드를 짤 수 있다.

std::string studentName; // string은 문자의 나열된 형태의 자료형. 일단 문자열 자료형이라 생각하면 됨
int studentClass;
int studentNumber;
float studentHeight;
float studentWeight;

이렇게 학생에 대한 정보를 짤 수 있지만, 여러 학생을 관리해야한다면 이런 5개의 변수를 새로운 변수이름과 함께 짜야하는데, 상당히 번거롭다.

구조체

하나 이상의 변수를 그룹 지어서 새로운 자료형을 정의하는 것

구조체 선언 및 정의

struct 구조체이름 // '구조체이름'이 자료형이 됨
{
	자료형 멤버변수1; // 각각의 자료형은 다를 수 있음
	자료형 멤버변수2;
	//...
}; // 세미콜론을 써줘야함
struct student 
{
	string name; // using namespace std를 사용한다는 가정을 하여 std에서 참조한다는 문법을 뺐음
	int classNum;
	int number;
	float height;
	float weight;
};

위의 학생에 대한 정보를 구조체로 새롭게 정의해본 것이다. student라는 새로운 자료형으로 변수를 하나 선언한다면 그 안의 string, int, int, float, float의 변수가 생기는 것이다. 이로써 일일이 변수를 선언할 필요가 없어졌다.

구조체 변수 선언 방법

student student1 = {"김철수", 1, 1, 175, 60.5}; // 구조체의 멤버 전부를 값을 넣어 초기화
student student2 = {"이영희", 2, 10, 154}; // 영희의 몸무게는 채워넣지 않았으므로 0으로 초기화
student s3; // 멤버 전부 쓰레기 값
struct student s4; // 키워드 struct를 붙일 수도 있음
student s5 = {"S5",1,1,1,1}, // 여러 개의 변수를 한 번에 선언하며 초기화할 수 있음
        s6 = {"S6",1,1,1,1};
student s7 {"S7",1,1,1,1}, // 대입연산자를 빼고 초기화할 수 있음
        s8 {"S8",1,1,1,1};

위의 코드로 실제 디버깅을 해본 결과이다. 왼쪽에 실제 구조체 내의 멤버 값들을 확인해보면 student1, student2는 초기값을 대입해주었기 떄문에 쓰레기 값이 없고 student2의 weight은 자동으로 0으로 초기화가 되었다. 하지만 student3는 초기값 자체를 주지 않았기 때문에 멤버 변수에 쓰레기 값으로 들어가있다.

구조체 멤버 접근

.
멤버 참조 연산자

student s3; // 구조체 변수 생성
s3.name = "박덕철";
s3.classNum = 3;
s3.number = 5;
s3.height = 183;
s3.weight = 80;

s3 구조체의 각각의 멤버에 접근하면서 각 멤버를 초기화해주고 있다. 멤버를 참조하고 싶은 구조체에 . 를 찍어 그 안에 있는 멤버의 이름을 써주면 일반 변수처럼 값을 다룰 수 있다.

구조체 단위의 값 대입

// 구조체의 값 대입
s3 = s5;
// 위의 대입 연산은 아래와 같이 하나씩 작업이 이루어짐
s3.name = s5.name;
s3.classNum = s5.classNum;
s3.number = s5.number;
s3.height = s5.height;
s3.weight = s5.weight;

패딩

구조체에 멤버 선언 순서에 따라서 공간을 차지하는게 달라질 수도 있다. 왜라는 의문이 생기겠지만 일단 다음과 같은 코드와 그 코드의 결과를 보자.

struct test1
{
    char c;
    long long i;
    char d;
};

struct test2
{
    long long i;
    char c;
    char d;
};

int main()
{
    cout << sizeof(char) << endl;
    cout << sizeof(long long) << endl;
    cout << sizeof(test1) << endl;
    cout << sizeof(test2) << endl;
}
// 출력 결과
// 1
// 8
// 24
// 16

char는 1바이트, long long은 8바이트이므로 1 * 2 + 8 = 10이여야하지 않은가?라는 생각이 들지만, test1, test2 그 어떤 구조체도 10이라는 크기를 갖고 있지 않는다. 이유는 패딩에 있다.

Padding
1.〈물건에〉 완충재를 대다, 속을 채우다, 부풋하게 하다, 〈상자 등에〉 가득 채우다, 〈옷에〉 패드를 넣다〔out

패딩의 뜻은 위와 같고 구조체의 메모리 패딩은 다음과 같다.

구조체 패딩

성능 향상을 위해 CPU가 접근하기 쉬운 위치에 필드를 배치하는 것

구조체 패딩은 구조체에서 가장 큰 자료형에 맞춰서 크기가 정해진다.

현재 우리가 구현한 두 개의 구조체에서는 long long 타입이 가장 크기 때문에 이 자료형의 크기인 8바이트에 맞춰 패딩의 크기가 결정된다. test1의 패딩 바이트는 char c와 함께 있는 7바이트, 그리고 long long은 패딩 바이트가 필요 없고, char d와 함께 있는 7바이트하여 총 8 + 8 + 8 = 24가 된다.

test2 구조체에서는 long long은 패딩 바이트가 필요 없으므로 넘어가고 char c, d 두 개의 char 자료형이니 2바이트이다. 그럼 8바이트를 맞추기 위해서는 6바이트의 패딩 바이트가 필요하다. 그렇기 때문에 8 + 8 = 16이 되어 구조체의 크기가 결졍되었다.

profile
성장과 성공, 그 사이 어딘가

0개의 댓글