[C++] 구조체 동적 할당

구조체를 동적할당하여 값을 직접접근하여 넣고 출력하기
#include <iostream>
#include <malloc.h>
#include <cstring>

using namespace std;

typedef struct studentTag {
    char name[10]; //char 1바이트 * 10 = 10바이트
    int age; //4바이트
    double gpa; //8바이트
} student;

int main()
{
    student* s;

    s = (student*)malloc(sizeof(student)); //student 구조체속 속성들의 크기합만큼 동적할당(10+4+8)=22바이트 할당

    /*24로 나오는 이유는 메모리의 정렬위함.
    * 
    * 구조체 속 name이 10바이트, age가4바이트, gpa가 8바이트인데 
    * 정렬이라함은
    * 가장 큰 단위씩 맞추기 위해 name에 2바이트를 추가하여 12, 4, 8로 정렬시킴.
    */
    cout << "학생구조체의 크기: " << sizeof(student) << " bytes" << endl;
    if (s == NULL) {
        cout << "메모리가 부족합니다.";
        return 1;
    }

    strcpy_s(s->name, "Park"); //문자열 student구조체 s의 name에 직접접근하여 Park을 복사해서 넣는다
    s->age = 20; // == (*).age = 20 과 동일함

    cout << "이름: " << s->name << " / 나이: " << s->age;

    free(s); //메모리해제

}

 

Malloc이란?
C와 C++에서 동적 메모리 할당때에 사용하는 함수
반환타입이 (void*)를 반환하기에 할당시킬 포인터 변수와 동일한 자료형을 캐스팅 해야합니다.
해제시에는 free()함수로 메모리를 해제 해야합니다.

 

구조체에 접근할 때에는 .보다는 ->로 하는 것이 직접적으로 접근하기 때문에 보기에도 좋습니다.

 

이번 내용에서 가장 유익했던 점
구조체를 malloc으로 메모리를 동적 할당하게되면 정렬을 위해 가장 큰 자료크기 단위로 할당하게 됩니다.

Student 구조체에
Char형 배열 10칸 = 1바이트*10 = 10바이트
int형 변수 하나  = 4바이트
double형 변수 하나 = 8바이트
= 총 22바이트
가 할당 될 줄 알았더니 24바이트가 할당되었습니다.

이유는
구조체의 Char형이 10바이트로 가장 큰 단위인 double의 8바이트 단위로 끊기지 않기때문에 2바이트를 추가하여 12바이트를 맞춘것입니다.
CPU가 데이터를 효율적으로 처리 하도록 메모리의 경계를 맞추기위해 추가시킨 것이라고 합니다.

 

이해가 제대로 안되던게 구조체 순서가 char name[10], int age, double gpa 면 가장 큰 단위인 double에 맞춰서

10(name) + (패딩:6) + 4(age) + (패딩:4) + 8(gpa) = 32가 나와야 한다 생각했는데,

구글링과 gpt로 알아보니 컴파일러가 메모리 정렬을 알아서 필요한 메모리만 할당해주기 위해 최적화시켜주어서

10(name) + (패딩:2) + 4(age)까지 16으로 맞춰지니 뒤에 8(gpa)만 추가하여 24로 할당된 것 이였습니다.

최적화가 안되었다면 32가 할당되는 것이였습니다.

 

다른 예시로 같은 코드지만 gpa와 age의 순서를 바꾼것입니다.

typedef struct studentTag {
    char name[10]; //char 1바이트 * 10 = 10바이트
    double gpa; //8바이트
    int age; //4바이트
} student;

객체지향도 순차적으로 읽기때문에 name다음 double을 읽습니다. 이때 8단위를 맞추기위해 name에 10바이트에 패딩은 2가 아니라 6을 추가시켜주어야합니다. 그래야 다음 gpa의 메모리 배치를 맞출 수 있기 때문입니다.

gpa 이후는 age도 8단위에 맞춰야하므로, name(10) + (6패딩) + gpa(8) + age(4) + (4패딩) = 32바이트 할당이 됩니다.

선언 순서에 따라서도 메모리 크기가 달라지기 때문에 크기가 작은 것 부터 선언하는것이 최적이라 볼 수 있겠습니다.