趣味プログラマによるOSS開発日誌

趣味で作っているOSSソフトウェアの紹介や関連技術の紹介、楽曲製作、Webデザイン勉強状況を紹介します。

サイズ0の配列を宣言することの利点

他の人が作成したプログラムを読んでいる時、以下のように構造体の中でサイズ0の配列を宣言しているソースを見かけました。

struct zero_struct
{
  int body[0];
};

通常であればサイズ0の配列宣言は意味のないものと考えられるのですが、あえて行うということは何か理由があるはずです。
そこで少し調べてみると、サイズ0として宣言することで可変長配列の時に役立つことが分かりました。
※ここで紹介しているのは、C99から含まれる仕様です。

可変長配列の実現例(単純に行う場合)

可変長配列を実現するためには、例えば以下のようなコードが考えられると思います。

#define ARRAY_SIZE 10

struct flex_array
{
  int* body;
};

int main()
{
  struct flex_array* arr;

  arr = (struct flex_array*) malloc(sizeof(struct flex_array));
  arr.body = (int*) malloc( sizeof(int) * ARRAY_SIZE );

  return 0;
}

可変長配列の実現例(サイズ0の配列を用いる場合)

次にサイズ0の配列を用いて、可変長配列を実現した例を示します。
サイズ0の配列を用いることにより、動的に確保した配列を指すポインタのサイズ分のメモリが節約できるとともに、struct flex_array分の割り当て処理も不要になりました。
効果としては微々たるものですが、知っておいて損はしないテクニックであると思います。

#define ARRAY_SIZE 10

struct flex_array
{
  int body[0];
};

int main()
{
  struct flex_array* arr;

  arr = (struct flex_array*) malloc(sizeof(int) * ARRAY_SIZE);

  return 0;
}

サンプルコード

最後にまとめとして、サンプルコードを示しておきます。

#include <stdio.h>
#include <stdlib.h>
 
#define ARRAY_SIZE 10
 
struct zero_struct
{
  int body[0];
};
 
int main()
{
  struct zero_struct z;
  struct zero_struct* zp;
  int i;
 
  printf("struct size : %d\n", sizeof(z));
 
  zp = (struct zero_struct*) malloc(sizeof(int) * ARRAY_SIZE);
 
  for (i = 0; i < ARRAY_SIZE; ++i){
    zp->body[i] = 0;
  }
 
  printf("exited successfully\n");
 
  return 0;
}

実行結果

$ gcc zero_struct_member.c -o zero_struct_member
$ ./zero_struct_member
struct size : 0
exited successfully