구조체 패딩에 관해서 문의드립니다

익명 사용자의 이미지

구조체에서 패딩되는 부분에 관해서 문의 드립니다.

#include<stdio.h>
typedef struct
{
  char ch;     /* char tmp[3]; */
  short  short_int;  
  int int_i;
}TEST;
int main()
{
  printf("[%d]",sizeof(TEST));
  printf("[%d]",sizeof(test.ch));
  printf("[%d]",sizeof(test.short_int));
  printf("[%d]",sizeof(test.int_i));
}

결과

Quote:
[8][1][2][4]

이런 현상이 일어납니다... 컴파일러가 구조체 중..가장 큰것으로 패딩한다고
그래서 이런 식으로 한다고 들었습니다 ??
그런데..문제는 제가 소켓 통신으로 header를 구현하는데...
이런 패딩없이 이론적인(?) 1+2+4 의 개수만큼만 보내주어야 하거든요..

질문1:고수님들은 이럴때 어떻게 하시는지??
질문2:(int 4로 안되고..2를 기준으로 패딩되었네요 ?? 왜 그러지..이게 디폴트인가? ) 그렇다면 어딘가에 2==>1로 바꾸는 부분이 있을 텐데.... 이것을 바꾸면 전체 시스템에 어떤 영향을 주는지??
:?:

codebank의 이미지

:oops:
사실은 저도 잘모르고 사용하는 바람에 정확한 이유는 잘 모르지만
대부분의 컴파일러가 프로그래머의 생각과는 다른 결과를 만들어내고는 있죠.
gcc, cc, MFC, borland-C 모두가 그러는데... 간단하게 생각해보면
빠른 속도 때문입니다. 메모리를 정렬 시키지않고 단번에 계산을 해볼려는
의도인데 단독으로 돌아가는 프로그램이라면 허용되는 이야기죠.
그런데 다른 프로그램과 통신을 한다거나 공유파일에 접근하려 한다면
이것이 문제가 되기도 합니다.

그래서 컴파일별로 따로 옵션을 두고 있습니다.
gcc로 작업을 한다면 gcc로 컴파일시 다음과같은 옵션을 붙이면 됩니다.

-mold-align

그런데 이것보다는 소스에 직접

#pragma align 1

이것을 삽입시켜주는게 좋습니다.
위 내용은 man gcc 하신다음에 alignment로 검색해보면 나오는 부분입니다.
패딩은 기준이 있긴한데 구조체를 보면 short가 먼저 나옵니다.
아마 그것을 기준으로 패딩이 되지 않았나 추측이 됩니다.
보통은 처음 나오는 변수의 형에 따라 패딩이 정해진다고(9x년도...) 이야기를
들었는데 요즘은 좀더 빠른 메모리정렬을 위해서 short나 int단위로 패딩이
이루어진다고 어디선가 흘러가는 이야기를 들은것 같네요. :-)

------------------------------
좋은 하루 되세요.

익명 사용자의 이미지

http://seiya.sogang.ac.kr/btar/han/comp/lang/c/hnu-2001-00401.html

http://kldp.org/script/bbs/read.php?table=qa2&no=3862&o[sc]=c&o[ss]=alignment&o[st]=a&o[at]=s&o[sct]=s&o[stt]=s

위에 답변 주신분께..감사합니다..그래두 조금더 궁금해서...&#52287;아 보다가 위의 자료를 &#52287;았습니다.
언제나 부족하다는것을 알고 있지만...알듯하다가도...하다보면...모르고~~
후....
그래도 위의 분처럼 답변을 주시니...항상 ~감사감사~~

구조체 align은 위의 링크를 따라가면....알수 있을듯 합니다.
모두 즐프되셍~~

choissi의 이미지

패딩을 적용하는 이유가 메모리 접근의 최적화인지라,
일부 환경에서는 구조체 선언을 아에 패딩을 고려해서 합니다.


typedef struct _PK_KOSPIJONG{
        char    id          [1]; /* Data ID 'S'           */
        char    filler      [3]; /* Filler                */
        short   index          ; /* 일련번호              */
        short   stime          ; /* 증전전송시간          */
        char    filler1     [1]; /*                       */
        char    updown      [1]; /* 등락구분              */
        char    filler2     [1]; /* 거래구분 -> filler변경(2002-09-30) */
        char    dongsigb    [1]; /* 관리/감리구분 */
        long    price          ; /* 현재가                */
        long    open           ; /* 시가                  */
        long    high           ; /* 고가                  */
        long    low            ; /* 저가                  */

중간 중간에 있는 필러가 그런 용도겠지요...
또 저 필러가.. 나중에 추가되는 데이터를 위해서 사용되기도
해서.. 패킷 전체 수정없이 정보추가도 가능해서
유용하기도 합니다.

울랄라~ 호기심 천국~!!
http://www.ezdoum.com

hilite1의 이미지

padding은 경우에 따라서 다르겠지만,
아래와 같이 현상위주로 다시 설명을 합니다.

char
short 이면

char
padding(char)
short

char
int 이면

char
padding(char)
padding(char)
padding(char)
int

위와 같이 다음에 오는 데이터형의 사이즈에 따라서
padding이 다르게 일어납니다.

다시말해서, 구조체의 구성요소가 short이면 2byte 메모리 형태로 짝을 이루게 앞이 padding되고, int이면 4bytes 메모리 형태로 짝을 이루려고 합니다.

이는 같은 machine에서 사용시에는 별 문제가 없으나 소켓프로그래밍등을 통하여 다른 machine으로 구조체를 전달시에 반드시 데이터 시리얼라이징(디시리얼라이징)을 해 주어야 올바로 될 수 있습니다.

물론 위의 예 처럼 padding을 고려한 구조체를 약속하여 사용하면 피할 수 있겠습니다.

허접 설명이었습니다.

pynoos의 이미지

#pragma align

은.. 아마 gcc 에서 안될지도...

대신 대부분의 compiler에서는

#pragma pack(1)

struct packet
{

};

#pragma pack() /* default */

요런 방법으로 사용합니다.

송지석의 이미지

어.. 저는 이렇게 사용했는데...
pack이 리눅이에서도 되는 줄 몰랐네요.

#ifdef  WIN32
#pragma pack(1)
#endif

typedef struct  tRequest{
    char  req;
    short sup;
    char  data[REQ_LEN-1];
#ifdef  WIN32
} RequestStruct;
#else
} __attribute__((packed)) RequestStruct;
#endif
se7en3rd의 이미지

해결책은 위의 분들께서 제시하셨으니깐, 덧붙여 설명을 좀 하자면...

메모리에서 CPU 레지스터로 한번에 읽어오는(fetch) 데이터의 크기 때문에 패딩이 일어납니다. 32비트 머신에서는 4바이트 씩이고 64비트 머신에서는 8바이트 씩이겠지요...

32비트 머신을 예로 설명을 드리자면,

struct A
{
char a;
short b;
long c;
};

struct A test[10];

이렇게 선언을 하면 메모리 맵상의 어딘가에 영역이 잡히겠죠

그런데 패딩이 없다고 가정하면,

0
-----------------------------------------------------
|a|bb|cccc|a|bb|cccc|a|bb|cccc|a|bb|cccc|...
-----------------------------------------------------

이런식으로 잡히겠죠...

fetch는 4바이트 단위로 이루어지니깐 먄약 첫번째 c를 접근하기 위해서는

2번의 fetch가 이루어져야 합니다.

0번째 바이트부터 3번째 바이트까지 4바이트를 읽어서 그중에 3번째 바이트를 먼저 취하고,

4번째 바이트부터 7번째 바이트까지 4바이트 읽어서 그중에 4~6번째 바이트를 취해서, 둘을 합해 최종 c의 값을 만드는 결과가 생기지요~

때문에 컴파일러가 패딩을 넣는 겁니다.

이런 방식으로 따져서 테스트 보면, 두번의 fetch가 필요한 구조체선언은 패딩이 들어가고, 한번의 fetch로 구조체 인수를 접근할 수 있는 구조체 선언은 패딩이 안들어가는걸 확인할 수 있습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.