pjk
조회 수 7245 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄 첨부
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄 첨부
CPU 레지스터는
32비트 운영체제일때 4바이트

64비트 운영체제일때 8바이트 단위로 메모리를 읽는다

구조체를 4바이트 단위로 끊어주는것을 "바이트 패딩" 이라고 한다.
 
구조체는 메모리에 어떤 식으로 저장될까


다음과 같은 소스를 보자.

#include <iostream>

typedef struct _TEST{
    char    cData;
    short   sData;
    int     iData;
} TEST;

int main()
{
    TEST *tData = new TEST;

    std::cout << "cData size : " << sizeof(tData->cData) << std::endl;
    std::cout << "sData size : " << sizeof(tData->sData) << std::endl;
    std::cout << "iData size : " << sizeof(tData->iData) << std::endl;
    std::cout << "TData size : " << sizeof(*tData) << std::endl;

    return 0;
}

 

TEST 구조체는 char형 데이터(1byte), short형 데이터(2byte), int형 데이터(4byte)를 가지고 있으므로 1+2+4=7byte의 크기를 가질 것 처럼 보인다. 하지만 이 소스를 컴파일하고 실행을 해보면 예상과 다른 결과가 나온다. 

image1.png

<그림 1>

멤버 변수가 cData(1) + sData(2) + iData(4) = 7임에도 불고하고 그 크기는 8바이트라고 하니 참 이상한 일이다.

이는 현재 우리가 쓰는 32비트 컴퓨터에서 32비트 컴파일러를 사용하였기 때문에 32비트 즉, 4바이트로 데이터를 처리하는 것에 가장 최적화되어 있기 때문에 데이터를 4바이트 공간으로 저장하기 때문이다.

이 tData란 구조체는 8바이트에 다음과 같이 저장되어 있다.

그림2.png

<그림2>

 

cData를 저장하고, 4바이트중에 3바이트가 남아있기 때문에 sData를 3바이트 중에 2바이트의 공간에 저장하고,
iData를 저장하려 하니 1바이트밖에 남아있지 않기 때문에 4바이트의 공간을 따로 만들어 저장하게 되는 것이다.

그럼 이제 위의 소스에서 변수 선언의 순서를 한 번 바꿔 보자.

typedef struct _TEST{   
    char cData;   
    int iData;   
    short sData;   
} TEST; 

 

멤버변수의 순서를 바꿨을 뿐인데 신기하게도 같은 구조체의 크기가 8에서 12로 늘어나버렸다.

image2.png

<그림3>

 

이처럼 컴파일러는 4바이트에 맞춰서 데이터를 저장하는 것을 볼 수 있다. 이것을 막으려면 어떻게 해야할까.
이것을 해결하려면 #pragma pack() 이라는 전처리어를 사용하면 된다.
구조체 하나를 더 추가한 다음 소스를 보자.

#include <iostream>

typedef struct _TEST{
    char    cData;
    int     iData;
    short   sData;
} TEST;

#pragma pack(1)
typedef struct _TEST2{
    char cData;
    int iData;
    short sData;
} TEST2;

int main()
{
    TEST *tData = new TEST;
    TEST2 *tData2 = new TEST2;

    std::cout << "tData size : " << sizeof(*tData) << std::endl;
    std::cout << "tData2 size : " << sizeof(*tData2) << std::endl;

    return 0;
}

 

#pragma pack(1)에서 1은 1바이트 단위로 저장하겠다는 것이다.

따라서 TData와 TData2의 멤버는 같으나 크기는 다른 것을 확인할 수 있다.

image3.png

<그림 4>

 

그렇다면, 왜 모두 1바이트로 해서 메모리의 낭비가 없도록 하지 않는 것일까?
초반에 애기했듯이 32비트 CPU에서는 4바이트(32비트)의 단위로 데이터를 처리하는 것이 가장 빠르게 때문이다. 즉, #pragma pack(1) 이라고 선언해놓고 원래대로 돌려놓지 않는다면 속도저하의 문제가 생길 수 있다.
따라서, 위의 소스에서 구조체 선언이 끝나는 부분에 #pragma pack(4)라고 선언해주어 할 것이다. 하지만, 여기에도 문제가 있다. 만약, 이 소스를 32비트의 PC가 아닌 다른 CPU가 장착된 장비에서 컴파일하게 된다면 어떻게 될 것인가. 예를 들면 임베디드 시스템 같은 8~16비트 CPU에서 말이다.
소스를 일일히 찾아서 CPU에 맞게 고쳐주고 다시 컴파일해야 되는 불편함과 어려움이 생기게 된다.

이럴때를 위해서 좀 더 우아하게 쓰는 코드가 있다.

#pragma pack(push, 1)   
typedef struct _TEST2{   
    char cData;   
    int iData;   
    short sData;   
}TEST2;   
#pragma pack(pop)

 

기존의 바이트를 스택에 push하고 1바이트 단위로 처리한다음 끝나는 부분에 원래의 바이트 단위를 pop해주는 코드이다. 
아래와 같은 코드를 사용하면 구조체 크기는 1바이트가된다.

#pragma pack(push, 1)   
typedef struct DATA{   
    char cData;      
}DATA;   
#pragma pack(pop) 

 


  1. No Image notice

    C Programming FAQs(한글번역 pdf문서)

    Date2014.03.18 Bymakersweb Views30620
    read more
  2. No Image

    비트 필드의 크기는 해당 유형의 크기를 초과할 수 없다.

    Date2023.04.25 CategoryC Bymakersweb Views2641
    Read More
  3. flexible array member 에 대해서

    Date2020.02.20 CategoryC Bymakersweb Views4424
    Read More
  4. C++로 플러그인 개발

    Date2019.12.08 CategoryC++ Bymakersweb Views3924
    Read More
  5. No Image

    배열과 포인터, 등가포인터 예제

    Date2019.01.16 CategoryC Bymakersweb Views3001
    Read More
  6. 싱글톤 객체생성 패턴에 대해서

    Date2018.07.01 CategoryC++ Bymakersweb Views5956
    Read More
  7. No Image

    함수포인터와 typedef로의 선언

    Date2018.02.03 CategoryC Bymakersweb Views3191
    Read More
  8. No Image

    예제소스를 통해 리틀엔디안(Little endian)과 빅엔디안(Big endian)의 차이점 알아보기

    Date2014.05.24 CategoryC Bypjk Views9974
    Read More
  9. switch와 if 중 어느 것이 더 빠른가

    Date2017.01.31 CategoryC Bymakersweb Views5235
    Read More
  10. No Image

    구조체 배열을 반환하는 함수를 반환하는 함수를 호출하여 구조체 멤버 배열 요소 접근하기

    Date2016.05.22 Bymakersweb Views12341
    Read More
  11. No Image

    c/c++문자열, 유니코드 관련 함수

    Date2015.07.09 Bymakersweb Views7546
    Read More
  12. No Image

    volatile이 정확히 어떤 의미를 가지는 건가요?

    Date2014.09.30 CategoryC Bypjk Views7185
    Read More
  13. No Image

    HEX(16진수) to ASCII(아스키) 변환 코드

    Date2014.08.24 Bypjk Views37012
    Read More
  14. No Image

    strcmp, wcscmp, _tcscmp

    Date2014.07.18 Bypjk Views12569
    Read More
  15. No Image

    클래스 멤버에 대한 액세스 제어

    Date2014.06.27 CategoryC++ Bypjk Views6875
    Read More
  16. unsigned형의 모든 상수에는 접미사 ‘U’를 사용하여야 한다.

    Date2014.05.24 CategoryC Bypjk Views40463
    Read More
  17. No Image

    void형 포인터

    Date2014.05.24 CategoryC Bypjk Views7339
    Read More
  18. No Image

    함수 포인터의 배열

    Date2014.05.24 Bypjk Views9937
    Read More
  19. 구조체 메모리 저장방식 #pragma pack

    Date2014.05.24 CategoryC++ Bypjk Views7245
    Read More
  20. No Image

    Bit fields(비트필드)

    Date2014.05.24 Bypjk Views5912
    Read More
  21. No Image

    영어를 C언어로, 또는 C언어를 영어로 변환 해주는 cdecl

    Date2014.03.19 Bymakersweb Views10818
    Read More
Board Pagination Prev 1 2 Next
/ 2