掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板2

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.29006

int a[0]; <=== この文は何を意味しますか?
投稿者---h3X(2006/11/23 15:52:13)


環境は Linux, gcc です。

ふと思ったのですが、次の文は何を意味しますか?

int a[0];

シンボルテーブルに'a'という変数名を登録するだけの意味を持つのでしょうか?


オープンソースを読んでいたときにも、以下のような構造体宣言を目にしました。

  struct Server
  {
          char            name[HOSTLEN+1];        /* server name, MUST BE FIRST HERE! */
          char            by[NICKLEN+1];
  
          int             downlinks;              /* number of direct downlinks */
          aClient         *down, *side;           /* down-link and side-link */
          aClient         *next;                  /* next server in list */
          aConfItem       *nline;                 /* N-line pointer for this server */
          aClient         *hnext;                 /* next server in server hash */
          aClient         *lastsptr;              /* last sender ptr from this server */
          ui32            servid;                 /* 32-bit servid where shortn is stored */
          char            sndot[1];               /* a dot before the shortn (.serv) */
          char            shortn[0];              /* 4-char short name for this serv */
  };


この構造体では、最後のメンバが

char shortn[0];

と宣言されています。

これらは、コンパイラにどのように解釈され、またどういった意図があり、このような宣言をするのかが分りません。


ご教授よろしくお願いいたします。


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:int a[0]; <=== この文は何を意味しますか? 29009 RAPT 2006/11/23 21:36:18
<子記事> Re:int a[0]; <=== この文は何を意味しますか? 29010 ぷはぁ 2006/11/23 21:43:27


No.29009

Re:int a[0]; <=== この文は何を意味しますか?
投稿者---RAPT(2006/11/23 21:36:18)


> char            shortn[0]
これは、「構造体の最後のメンバである」と明示した場合、特別の意味を持ちます。
# 逆にそれがなければ意図不明でした。。

構造体の最後のメンバに自由な大きさの配列をもたせることができるように
するための技法といえば良いでしょうか。

> ui32            servid;
で指定したサイズ分有効な大きさの shortn となるのでしょう。
これは下記のように自由な大きさの要素を1つの構造体で表現できます。
+-----+-----+-----+
| (a) | (b) | (c) |
+-----+-----+-----+
+-----+-----+-------…--+
| (a) | (b) | (c)   …  |
+-----+-----+-------…--+

最後の要素であれば、他のメンバとの位置がずれる事がないので問題なく
使えます。また、この場合、char a[100] とかしても無意味となりますが、
識別子を省略できないので、char a[0] とか書く事が多いようです。




この投稿にコメントする

削除パスワード

No.29011

Re:int a[0]; <=== この文は何を意味しますか?
投稿者---h3X(2006/11/23 22:08:45)


ご返信ありがとうございます。

>これは、「構造体の最後のメンバである」と明示した場合、特別の意味を持ちます。
># 逆にそれがなければ意図不明でした。。

そうですか。。以下のような構造体の宣言もあったのですが。。

struct Client
  {
  #if defined(__cplusplus)||defined(c_plusplus)
          union { char name[HOSTLEN+1]; anUser u[1]; aServer srv[1]; };
  #else
          char    name[0];        /* name leeching off of user/serv info area */
          anUser  u[0];           /* static equiv of cptr->user */
          aServer s[0];           /* static equiv of cptr->serv */
          union { anUser u; aServer s; } idata;
  #endif
  
          aClient *hnext, *prev, *next, **hbase;
          aClient *from;          /* == self, if Local Client, *NEVER* NULL! */
          aClient *srvptr;        /* server introducing this.  may be &me. */     
          
          ui32    umodes; /* user modes */
          ui32    flags;  /* client flags */


以下長々と続くので省略します。

この場合は、

char name[0];
anUser u[0];
aServer s[0];

はどういった意図でこのように宣言されているのか理解に苦しみます。


>構造体の最後のメンバに自由な大きさの配列をもたせることができるように
>するための技法といえば良いでしょうか。

それなら、構造体に

char *shortn;

と宣言すればいいように思いますが、、、どうなんでしょうか?


この投稿にコメントする

削除パスワード

No.29014

Re:int a[0]; <=== この文は何を意味しますか?
投稿者---Hermit(2006/11/24 00:00:54)


>char name[0];
>anUser u[0];
>aServer s[0];
>はどういった意図でこのように宣言されているのか理解に苦しみます。

C++ を良く知らないので、勘ですが、
C++ と、C の書き方が違うため、C++ 形式で呼び出せるようになっているだけではないでしょうか。
gcc では、サイズ0のメンバーを認めているため、
name,u,s,union{}idata のポインタは同じになります。
ただし、最後のメンバ C++ 側は、srv C 側は s なので、ここだけ同じには出来そうに無い気がしますが。

>それなら、構造体に
>char *shortn;
>と宣言すればいいように思いますが、、、どうなんでしょうか?
そうすると、shortn に、もう一度 malloc で、文字列洋の領域を確保する必要があるので、
その分のオーバーヘッド、領域を多く使用してしまう、
処理が多くなることによるバグの可能性、
free() のしわすれなどの可能性などある為、
一括にすることが多いようです。


この投稿にコメントする

削除パスワード

No.29019

Re:int a[0]; <=== この文は何を意味しますか?
投稿者---h3X(2006/11/24 07:46:46)


>そうすると、shortn に、もう一度 malloc で、文字列洋の領域を確保する必要があるので、
>その分のオーバーヘッド、領域を多く使用してしまう、
>処理が多くなることによるバグの可能性、
>free() のしわすれなどの可能性などある為、
>一括にすることが多いようです。

やっぱりそういう利点のためにやってるんですか。

確かに領域確保や、解放は一括の方が楽ですね。

ありがとうございました。


この投稿にコメントする

削除パスワード

No.29018

Re:int a[0]; <=== この文は何を意味しますか?
投稿者---ぽへぇ(2006/11/24 01:30:19)


参考までに貼っておきますね
http://www.kouno.jp/home/c_faq/c2.html#6
http://seclan.dll.jp/c99d/c99d04.htm#dt19990726

>char *shortn;
>と宣言すればいいように思いますが、、、どうなんでしょうか?

>char* shortn;
hoge.shortn = "hogehoge"; // できる

>char shortn[0];
hoge.shortn = "hogehoge"; // できない

構造体(共用体)と抱き合わせで使って、
コードの書き方にある程度制限を設けてバグ回避
ってのもあったかも。



この投稿にコメントする

削除パスワード

No.29020

Re:int a[0]; <=== この文は何を意味しますか?
投稿者---h3X(2006/11/24 07:48:36)


>参考までに貼っておきますね
>http://www.kouno.jp/home/c_faq/c2.html#6
>http://seclan.dll.jp/c99d/c99d04.htm#dt19990726

参考URLありがとうございました。

特に2番目のURLの情報は大変参考になりました。


この投稿にコメントする

削除パスワード

No.29010

Re:int a[0]; <=== この文は何を意味しますか?
投稿者---ぷはぁ(2006/11/23 21:43:27)


Borland C++ Compilerでは、
「配列には最低 1 個の要素が必要」という
コンパイルエラーが発生する。
処理系によって使えたり使えなかったりするのであろう。



この投稿にコメントする

削除パスワード

No.29012

Re:int a[0]; <=== この文は何を意味しますか?
投稿者---Hermit(2006/11/23 23:14:54)


>Borland C++ Compilerでは、
>「配列には最低 1 個の要素が必要」という
>コンパイルエラーが発生する。
>処理系によって使えたり使えなかったりするのであろう。

ANSI では、サイズ 0 のメンバーは認めないため、
エラーになることが多いようです。

gcc では、
char mem[0]; // 0バイトのメンバ
昔、MSC,turbo C では、
char mem[]; // これで 0 バイトのメンバー
となっていたようですが、今はよくわかりません。

malloc(sizeof(STRUCT)+strlen(string)+1);
などのように、最後に文字列をくっつける時に使うことが多いのですが、
他で使う場合は、使用法は・・・あまりわかりません。

現在は、どのような処理系でもいいように、ANSI に従って、
char mem[1];
で、文字の終端文字 '\0' 分の +1 を書かない形式が多いようですが、
パディングの関係で、最適な領域になるとは限りません。


この投稿にコメントする

削除パスワード

No.29068

Re:int a[0]; <=== この文は何を意味しますか?
投稿者---breakwind4u(2006/11/27 11:20:32)


C++ では無名共用体を認めていますが、C では認められません。

> union { char name[HOSTLEN+1]; anUser u[1]; aServer srv[1]; };

これが「無名共用体」です。

Client c; に対して、c.name, c.u, c.srv は同じアドレスに配置されます。

C の場合、共用体は無名にできませんので、下記のようになります。
> union { char name[HOSTLEN+1]; anUser u[1]; aServer srv[1]; } idata;

しかし、この場合だと、c.idata.name, c.idata.u みたいに、C/C++ で
アクセス方法が変わってしまいます。

そこで、
> char name[0];
> anUser u[0];
> aServer s[0];
> union { anUser u; aServer s; } idata;
のように、サイズ 0 の配列を使って name, u, s, idata を同じアドレスに
配置した上で、idata によって必要なサイズを確保しているのでしょう。

idata は、必要なサイズ(次のメンバまでのオフセット)を確保するため
だけの目的なので、実際に idata 経由で u, s にアクセスしている部分は
無いと思います。

#ちなみに、C++ の場合は aServer srv[1]; なのに C の方は aServer s[0];
#となっています。typo でしょうか?



この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧