2018年7月29日日曜日

C言語疑問とメモ:構造体の宣言と定義

以下の内容は個人的メモであり、誤りが含まれている可能性があります。ご注意ください。
CについてはN1570を、C++についてはN3337を参照しています。

構造体の宣言と定義

struct Tag {
    char member1;
    int member2;
};

これは何を意味するか考える。

構造体・共有体指定子中の{...}部分(の存在)は、その翻訳単位内で新しい型の宣言をする。(6.7.2.1p8)

{...}を含む構造体、共有体、列挙型の型指定子は、それぞれの型を宣言する。
{...}の部分は、それらのコンテンツを定義する。
型指定子に識別子が提供された場合、その型指定子はその型のタグとなる識別子も宣言する。(6.7.2.3p6)

(6.7.2.3 Tagsの制約として)ある型は、最大一回だけ定義されたコンテンツ(内容)を持たなければならない(持てる?)(shall have)(6.7.2.3p1)

コンテンツとは、(6.7.2.3p6)から、構造体の持つ要素であると言える。

同じタグを持ち、同じスコープを持つ構造体型、共有体型、列挙型の宣言は、同じ型を宣言する。(6.7.2.3p4)
ある翻訳単位に、ある型のタグや他の宣言があるかどうかにかかわらず、コンテンツの定義のとじカッコ(})が現れるまでは不完全型であり、その直後に完全型となる。(6.7.2.3p4)

識別子は、オブジェクト、関数、構造体や共有体や列挙のメンバ名かタグ、typedef名、ラベル名、マクロ名、マクロ仮引数を、一つ示す(意味する、表す)ことができる。(6.2.1p1)
宣言は識別子の解釈と属性を明示する。(6.7p5)
オブジェクトのストレージの割当を引き起こす、オブジェクトの識別子の宣言は定義である。(6.7p5)
関数の本体を含む識別子の宣言は定義である。(6.7p5)

なお、無名の構造体(タグも識別子も持たない、構造体のコンテンツの定義のみを行う)は文法上構造体などの内部でしかできないと思う(ちゃんと確認はしていない)(6.7.2.1p1)

以上のことから、最初のコード片は、
「新しい構造体型の宣言と、構造体を示す識別子(=タグ)の宣言であり、さらにその識別子が示す構造体型のコンテンツを定義している」
と考える。

C++では少なくとも、宣言のうち定義でないものが明確であり(3.1p2)、一般的な意味での「クラスの定義」とは何であるかはわかりやすい。(9p2)
C++の方が、部分的にはわかりやすい気がします。

0 件のコメント:

コメントを投稿