struct
読み:ストラクト
外語:struct

 C/C++の予約語の一つ。
目次

概要
 構造体を定義するのに使う。

特徴

匿名構造体
 Cの標準仕様では、structには名前が必須である。
 C++の場合、C++の特殊な機能を使っていない場合に限り、構造体や共用体を別の構造体や共用体に埋め込む場合には、その内部の構造体や共用体に名前を付ける必要がない。またこの場合、参照する際にも構造体や共用体の名前を付けなくても内容にアクセスすることができる。

GCC拡張
 GCCおよびclang/LLVMでは、C++だけでなくC言語でも匿名構造体が利用できる。
struct A {
    struct {
        int i, j;
    };
};
int foo(int var)
{
    struct A a;
    a.i = 123;
    printf("%d\n", a.i);
    return 0;
}
 内部のstructには名前がなくても、外部のstructから呼び出すことができる。
 この機能は便利だが、バグを呼ぶ危険もあることから、#pragma anon_unionsと#pragma no_anon_unionsで、ON/OFFできるようにした実装もある。

使用方法

二種類の定義方法
 構造体を定義するとき、typedef structとstructの二種類がある。この違いは何か。
 例えば、次の構造体を定義するとする。
struct tagPoint {
    int x;
    int y;
};
typedef struct tagPoint Point_t;
Point_t p1, p2;
 この時、最初のstruct構文は、tagPoint構造体型を定義している。次のtypedefでPoint_t型を別名定義している。
 最後は、Point_t型の変数p1とp2を定義している。これは、次のように書いたことと同じである。
struct tagPoint p1, p2;

応用
 struct構文は、組み合わせによって、次の表記が可能となっている。

typedef struct
 構造体を定義し、さらに型の別名を付ける方法。
typedef struct tagPoint {
    int x;
    int y;
} Point_t;
 この方法を使えば、最初から別名定義することが分かっている場合、構造体を定義した後でさらにtypedefする手間が省ける。
 なお、以降別名のみを用いる場合、構造体型は必要がない。そこで、次のように構造体型を記述しない定義も可能である。
typedef struct {
    int x;
    int y;
} Point_t;

変数宣言の融合
 構造体を定義し、さらにその型の変数も同時に宣言する方法。
struct tagPoint {
    int x;
    int y;
} p1, p2;

違い
 typedef structと、structは似ているが、実際にはしていることが違う。
 typedef struct tagPoint {…} Point_tは、構造体をtagPointという名前の構造体型で定義し、さらにPoint_tという名前の構造体型で別名定義している。
 一方、typedefが無い場合のstruct tagPoint {…} p1, p2は、型の別名定義ではなく、構造体の定義と変数宣言をしている。tagPointという名前の構造体型を定義し、さらにtagPoint型の変数p1とp2を宣言しているのである。

補足

C++
 C++ではCより意味が拡張され、ほぼclassの同義語として使用される。
 classとの違いは、メンバーへのアクセス指定のデフォルトがpublicであることと、継承がデフォルトでpublic継承になることの2点のみである。
 Cと互換がなくなり、「extern "C"」で外部宣言されるC関数とリンクできなくなるが、structもclassと同様にコンストラクターデストラクターが存在する。

C++11
 C++11では、enum定義において、スコープ付きの列挙型を宣言する場合にも用いる。
 enum struct/enum classは、どちらで書いても同義となる。

再検索