본문 바로가기

IT/C++ Programming

C99 Flexible array member

/* 
written by kaspy (kaspyx@gmail.com)
*/ 


GNU C 컴파일러에는 배열의 크기를 0으로 하고 이를 가변 배열로 메모리로 할당하여 사용하는 경우가 있다. 일명 가변 배열이라고도 하는데 배열의 크기를 유동적으로 정해줄수있다. 대략 아래 코드같이.. 구조체의 멤버 배열의 크기를 "0" 으로 잡고 사용하는 방법인데 C99 전에는 일명 꼼수로 배열크기 1([1]) 사용되어 왔는데 C99 부터는 공식적으로 0의 크기를 주거나 '[]'만 줘서 유동적인 배열크기를 잡을수 있다.


  1. struct line {
  2.     int length;
  3.     char contents[0]; /* Here */
  4. };
  5.  
  6. struct line *thisline = (struct line *)
  7. malloc (sizeof (struct line) + this_length);
  8. thisline->length = this_length;


컴파일러 버전이나 환경등에 따라 다르겠지만 Flexible array의 특징은 아래와 같다

(may로 나와있는것으로 봐서 반드시 해당하진 않는것으로 생각된다.)

  • Flexible array는 위에서 2 line 처럼 'contents[]'로 만줘서도 선언이 가능하다
  • Flexible array는 불완전 타입으로 sizeof 연산을 사용하면 안된다.
  • Flexible array는 구조체에서 마지막 멤버로써만 사용되는데 구조체의 사이즈가 0이 아닌것을 나타내기 위해서이다.(만약 length 선언이 없다면 컴파일 에러)
  • 구조체나 공용체에 포함된 Flexible array는 멤버로 사용되면 안된다
GCC 버전의 같은경우 f1 구조체는 f2처럼 선언한것처럼 편리하게사용할수있다. 


  1.      struct f1 {
  2.        int x; int y[];
  3.      } f1 = { 1, { 2, 3, 4 } };
  4.      
  5.      struct f2 {
  6.        struct f1 f1; int data[3];
  7.      } f2 = { { 1 }, { 2, 3, 4 } };


아래는 선언 할때 몇가지 주의점이다.


  1.      struct foo { int x; int y[]; };
  2.      struct bar { struct foo z; };
  3.      
  4.      struct foo a = { 1, { 2, 3, 4 } };        // Valid.
  5.      struct bar b = { { 1, { 2, 3, 4 } } };    // Invalid.
  6.      struct bar c = { { 1, { } } };            // Valid.
  7.      struct foo d[1] = { { 1, { 2, 3, 4 } } };  // Invalid.


물론 data structure alignment를 보장하지 않는다는점이 위험할수있으므로 사용을 지향할순 없지만 때때로는 유용하게 사용될수도 있다.

동적 메모리 할당 등에도 사용할수 있다. 아래는 Flexible array member를 사용한 간단한 코드이다. 


  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. struct node{
  5.   int len;
  6.   char name[];
  7. };
  8.  
  9. void name_alloc(char *name){
  10.   struct node *pnode;
  11.   pnode = malloc(sizeof(struct node) + strlen(name) );
  12.   pnode->len = strlen(name);
  13.   strcpy(pnode->name ,name );
  14.   printf("lenth = %d\n",pnode->len);
  15.   printf("%s\n",pnode->name );
  16.  
  17.   free(pnode);
  18. }
  19.  
  20. int main()
  21. {
  22.   name_alloc("kim kyng-su");
  23.  
  24.   return 0;
  25. }


참조 링크 

- https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html