본문 바로가기
Dev./Sec. Study/C/C++

Struct Hack

by 로제마인 2012. 8. 23.

출처 : http://www.geeksforgeeks.org/archives/22677




요는, length가 0인 array가 포함된 구조체의 메모리 사이즈를 크게 잡으면


멤버인 length 0짜리 array를 동적할당 하듯이 쓸 수 있다는 말인 듯.



구조체를 sizeof (struct __) 만큼이 아니라, 그 이상으로 원하는 만큼 더 잡아서


멤버 array 를 쓰겠다는건데..


array length 0 은 궁금했지만 해보진 않았는데, 이런 효과가 -ㅅ-;;



단순히 동적할당 할 뿐이지만, 잘 쓰면 괜찮은 방법일 듯.


C99 에 명시된 방법이라곤 하는데, 특정 플랫폼의 gcc가 아닌 컴파일러에서도 동작하느냐가 궁금하군요.



코드에 오류라던가 조금 보이는거 같지만, 알아서 걸러봐야겠네요.


Struct Hack

August 14, 2012

What will be the size of following structure?


struct employee

{

    int     emp_id;

    int     name_len;

    char    name[0];

};

4 + 4 + 0 = 8 bytes.


And what about size of “name[0]“. In gcc, when we create an array of zero length, it is considered as array of incomplete type that’s why gcc reports its size as “0″ bytes. This technique is known as “Stuct Hack”. When we create array of zero length inside structure, it must be (and only) last member of structure. Shortly we will see how to use it.

“Struct Hack” technique is used to create variable length member in a structure. In the above structure, string length of “name” is not fixed, so we can use “name” as variable length array.


Let us see below memory allocation.


struct employee *e = malloc(sizeof(*e) + sizeof(char) * 128); 

is equivalent to


struct employee

{

    int     emp_id;

    int     name_len;

    char    name[128]; /* character array of size 128 */

};

And below memory allocation


struct employee *e = malloc(sizeof(*e) + sizeof(char) * 1024); 

is equivalent to


struct employee

{

    int     emp_id;

    int     name_len;

    char    name[1024]; /* character array of size 1024 */

};

Note: since name is character array, in malloc instead of “sizeof(char) * 128″, we can use “128″ directly. sizeof is used to avoid confusion.


Now we can use “name” same as pointer. e.g.


e->emp_id = 100;

e->name_len = strlen("Geeks For Geeks");

strncpy(e->name, "Geeks For Geeks", e->name_len);


When we allocate memory as given above, compiler will allocate memory to store “emp_id” and “name_len” plus contiguous memory to store “name”. When we use this technique, gcc guaranties that, “name” will get contiguous memory.

Obviously there are other ways to solve problem, one is we can use character pointer. But there is no guarantee that character pointer will get contiguous memory, and we can take advantage of this contiguous memory. For example, by using this technique, we can allocate and deallocate memory by using single malloc and free call (because memory is contagious). Other advantage of this is, suppose if we want to write data, we can write whole data by using single “write()” call. e.g.


write(fd, e, sizeof(*e) + name_len); /* write emp_id + name_len + name */ 


If we use character pointer, then we need 2 write calls to write data. e.g.


write(fd, e, sizeof(*e)); /* write emp_id + name_len */

write(fd, e->name, e->name_len); /* write name */


Note: In C99, there is feature called “flexible array members”, which works same as “Struct Hack”


This article is compiled by Narendra Kangralkar. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above