[解決済み] 要素数0の配列の必要性とは?
質問
Linuxカーネルのコードの中に、以下のような理解不能なものがあります。
struct bts_action {
u16 type;
u16 size;
u8 data[0];
} __attribute__ ((packed));
コードはこちらです。 http://lxr.free-electrons.com/source/include/linux/ti_wilink_st.h
要素が0個のデータの配列の必要性と目的は何ですか?
どのように解決するのですか?
これは、データのサイズを可変にするために、わざわざ
malloc
(
kmalloc
を2回使用します。このように使うことになります。
struct bts_action *var = kmalloc(sizeof(*var) + extra, GFP_KERNEL);
これは以前は標準ではなく、(Aniket が言うように) ハックと見なされていましたが C99 で標準化されました。 . 今の標準的な書式は
struct bts_action {
u16 type;
u16 size;
u8 data[];
} __attribute__ ((packed)); /* Note: the __attribute__ is irrelevant here */
のサイズについて何も言及していないことに注意してください。
data
フィールドのサイズについて何も言及していないことに注意してください。また、この特別な変数は構造体の末尾にしかないことにも注意してください。
C99では、この件は6.7.2.1.16で説明されています(強調)。
特殊なケースとして、複数の名前付きメンバを持つ構造体の最後の要素は、不完全な配列型を持つことがあります。 は不完全な配列型を持っています。 これをフレキシブル配列メンバと呼びます . ほとんどの場合 は無視されます。特に,構造体のサイズは 構造体のサイズは,フレキシブル配列のメンバが省略された場合と同じですが, 後続のパディングは省略された場合よりも多くなる可能性があります. を省略した場合と同じです。ただし、.演算子(または->)が左オペランドを持つ場合、そのオペランドは (へのポインタ)であり、右オペランドがそのフレキシブル配列のメンバを指定するものであるとき を指定した場合,そのメンバを(同じ要素型を持つ)最長の配列に置き換えたように動作します. 構造体がアクセスされるオブジェクトより大きくならないような最長の配列(同じ要素タイプ)に置き換えたように動作する。 配列のオフセットは,柔軟な配列メンバのオフセットと異なる場合でも,そのオフセットのままでなければならない。 配列のオフセットは,たとえそれが置換配列のオフセットと異なっていても,柔軟な配列メンバのオフセットのままでなければならない。この配列が要素をもたない場合は,あたかも一つの要素をもつかのようにふるまう。 しかし,その要素にアクセスしようとしたり,その要素の一つ前のポインタを生成しようとしたりすると,その動作は不定になる。 要素にアクセスしようとしたり、過去のポインタを生成しようとした場合の動作は未定義です。
あるいは言い換えれば、持っている場合。
struct something
{
/* other variables */
char data[];
}
struct something *var = malloc(sizeof(*var) + extra);
にアクセスすることができます。
var->data
にインデックスを付けて
[0, extra)
. ただし
sizeof(struct something)
は他の変数を考慮したサイズしか与えませんので、 つまりは
data
を0にします。
また、この規格が実際にどのように
malloc
がそのような構成であることに注目してください (6.7.2.1.17)。
struct s { int n; double d[]; };
int m = /* some value */;
struct s *p = malloc(sizeof (struct s) + sizeof (double [m]));
同じ場所の規格によるもう一つの興味深い注意点は、(強調)です。
malloc の呼び出しが成功したと仮定すると、p が指すオブジェクトは、ほとんどの目的のために、p が宣言されていたかのように振る舞います。
struct { int n; double d[m]; } *p;
(この等価性が崩れる状況もあります。特に メンバーdのオフセットは同じではないかもしれません。 ).
関連
-
C 構造体定義エラー: '['トークンの前に一次式があることが予想される
-
警告:代入がキャストなしで整数からポインタを作成する場合の修正方法に関する警告
-
C/C++の再定義
-
[解決済み] 配列の場合、なぜ a[5] == 5[a] になるのでしょうか?
-
[解決済み] C言語における「static」の意味とは?
-
[解決済み] C言語で配列のサイズを決定するにはどうすればよいですか?
-
[解決済み] 配列のすべてのメンバーを同じ値で初期化するには?
-
[解決済み] C言語でのブーリアン値の使用
-
[解決済み] アセンブリがCより速いのはどんなとき?[クローズド]
-
[解決済み] ストラクチャーとユニオンの違い
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
コンパイルエラー:可変長オブジェクトが初期化されていない可能性があります。
-
警告:符号付き整数式と符号なし整数式の比較 [-Wsign-compare]
-
[解決済み] flexible array member not at end of structエラーの原因は何ですか?
-
[解決済み] ⑭と⑯は何のためにあるのですか?
-
[解決済み] c または c++ 用のシンプルな 2 次元クロスプラットフォームグラフィックスライブラリ?[クローズド]
-
[解決済み] 演算子 *, /, +, -, % を使わずに 3 で割る。
-
[解決済み] while ( !feof (file) ) 」は、なぜいつも間違っているのですか?
-
[解決済み] longをフォーマットするprintfの引数は何ですか?
-
[解決済み] なぜ16進数には0xがつくのですか?
-
[解決済み] C/C++で0サイズの配列を定義するとどうなりますか?