これにより、C++ではエラーが発生しますが、Cではエラーが発生しません。
typedef struct nodes
{
int data;
struct node *next;
}node;
C++では次のエラーが発生します。
/home/DS cpp/linkedlist.cpp|10|error: conflicting declaration ‘typedef struct nodes node’|
/home/DS cpp/linkedlist.cpp|9|error: ‘struct node’ has a previous declaration as ‘struct node’|
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
C++で動作させるには、次のように変更する必要があります。
typedef struct node
{
int data;
struct node *next;
}node;
私はこれがなぜ起こるか理解していません、私はそれを理解できるようにCとC++の両方で実行の順序を知りたいです。
コードを少し分析してみましょう。
typedef struct nodes
{
int data;
struct node *next;
}node;
これは、2つのメンバーを持つ型struct nodes
を宣言および定義し、node
としてのみ参照できるように型エイリアスを宣言します。
現在、C++では、メンバー宣言struct node *next
node
と呼ばれる型を自動的に前方宣言します 。それはあなたのtypedef
ターゲットnode
と衝突します:2つの型に同じ名前を与えようとしているようです。
Cでは、node
と呼ばれる型は実際にはstruct node
とのみ呼ばれるため、競合はありません。
2番目のスニペットが機能したのは、メンバー宣言の解析中にstruct node
がすでに存在するため、そこに新しい型は前方宣言されていないためです。そして、同じtypedef
ステートメント、C++はまったく気にせず、すべて同じタイプであることを知っている(struct T
isT
;違い名前ではなく構文にあります)。
[C++11: 7.1.3/3]:
指定された非クラススコープでは、typedef
指定子を使用して、そのスコープで宣言されている任意の型の名前を再定義し、既に参照している型を参照できます。 [例:typedef struct s { / ... / } s; typedef int I; typedef int I; typedef I I;
—例の終了]
[C++11: 7.1.3/6]:
特定のスコープでは、typedef
指定子を使用して、そのスコープで宣言された型の名前を再定義して、異なる型を参照しないでください。 [例:class complex { / ... / }; typedef int complex; // error: redefinition
—例の終了]
もちろん、C++では、これはすべて意味がないので、次のように記述する必要があります。
struct node
{
int data;
node* next;
};
typedef
--elaborated-type-specifierstruct
を離れる必要はありません。
指定したCの例はエラーになります。 struct node
で定義していないタグ名(node
)を使用しています。
これら2つの選択肢がある場合、2番目の選択肢が使用されます。私は少し経済を好む:
typedef struct node_t
{
int data;
struct node_t *next;
} node_t;
CまたはC++では、タグ名には独自の名前空間があるため、タグとtypedef名に同じ名前を使用しても問題はありません。 Cでは、これにより、node_t
またはstruct node_t
のいずれかを使用して、この構造体型を参照できます。 C++は、宣言されたタイプ名が存在しない場合、タグ名からタイプ名を検索します。したがって、上記の二重定義は必要ありませんが、害はありません。
どちらの言語でも、型が完全に定義される前の任意の時点で明示的なstruct node_t
バージョンが必要なので、自己参照および前方参照はstruct
バージョンを使用します。主に#include
ディレクティブの順序に関する問題を減らすため、ヘッダーファイルでこれを好みます。
PS:これはdoesどちらの言語でも動作し(C++ 11標準へのポインターについてはLRIOの回答を参照)、十分なバイリンガルおよび純粋なC++ヘッダーファイルでも使用されており、すぐに消えることはほとんどありません)どちらの言語でも機能する非常にシンプルなアプローチです。