55

C99では、構造体の柔軟な配列メンバーを次のように宣言できます。

struct blah
{
    int foo[];
};

しかし、ここで働いている誰かがC ++でclangを使用してコードをコンパイルしようとすると、その構文は機能しませんでした。(MSVCで動作していました。)次のように変換する必要がありました。

struct blah
{
    int foo[0];
};

C ++標準を調べたところ、柔軟なメンバー配列への参照はまったく見つかりませんでした。私はいつも[0]無効な宣言だと思っていましたが、柔軟なメンバー配列の場合は明らかに有効です。柔軟なメンバー配列は実際にC++で有効ですか?もしそうなら、正しい宣言[]ですか[0]

4

10 に答える 10

32

C++ は 1998 年に初めて標準化されたので、柔軟な配列メンバーが C に追加される (C99 で新しく追加された) よりも前のことです。2003 年に C++ の正誤表がありましたが、関連する新機能は追加されていません。C++ (C++2b) の次のリビジョンはまだ開発中であり、柔軟な配列メンバーはまだ追加されていないようです。

于 2010-12-10T20:04:55.193 に答える
28

0C++ は、空のインデックス表記またはインデックス表記 (ベンダー固有の拡張機能を除く)のいずれかを使用して、構造体の末尾にある C99 フレキシブル配列メンバーをサポートしません。

struct blah
{
    int count;
    int foo[];  // not valid C++
};

struct blah
{
    int count;
    int foo[0]; // also not valid C++
};

私の知る限り、C++0x もこれを追加しません。

ただし、配列のサイズを 1 要素にすると、次のようになります。

struct blah
{
    int count;
    int foo[1];
};

コードはコンパイルされ、非常にうまく機能しますが、技術的に未定義の動作です。オフバイワン エラーが発生する可能性が低い式を使用して、適切なメモリを割り当てることができます。

struct blah* p = (struct blah*) malloc( offsetof(struct blah, foo[desired_number_of_elements]);
if (p) {
    p->count = desired_number_of_elements;

    // initialize your p->foo[] array however appropriate - it has `count`
    // elements (indexable from 0 to count-1)
}

そのため、C90、C99、および C++ の間で移植可能であり、C99 の柔軟な配列メンバーと同様に機能します。

Raymond Chen はこれについて素晴らしい記事を書きました:なぜいくつかの構造体はサイズ 1 の配列で終わるのですか?

注: Raymond Chen の記事では、「柔軟な」配列を初期化する例にタイプミス/バグがあります。それは読むべきです:

for (DWORD Index = 0; Index < NumberOfGroups; Index++) { // note: used '<' , not '='
  TokenGroups->Groups[Index] = ...;
}
于 2010-12-10T20:31:21.827 に答える
4

2つ目は要素を含まず、。の直後を指しますblah。したがって、次のような構造がある場合:

struct something
{
  int a, b;
  int c[0];
};

あなたはこのようなことをすることができます:

struct something *val = (struct something *)malloc(sizeof(struct something) + 5 * sizeof(int));
val->a = 1;
val->b = 2;
val->c[0] = 3;

この場合c、5秒の配列として動作しますintが、配列内のデータはsomething構造体の後にあります。

私が取り組んでいる製品は、これをサイズ変更された文字列として使用しています。

struct String
{
  unsigned int allocated;
  unsigned int size;
  char data[0];
};

サポートされているアーキテクチャのため、これは8バイトプラスを消費しますallocated

もちろん、これはすべてCですが、たとえばg++は問題なく受け入れます。

于 2010-12-10T20:01:56.060 に答える
-2

より良い解決策は、それをポインターとして宣言することです。

struct blah
{
    int* foo;
};

または、さらに良いことに、次のように宣言しますstd::vector

struct blah
{
    std::vector<int> foo;
};
于 2010-12-10T20:04:00.880 に答える