2016-03-28 3 views
0

私はC言語に新しく、(古典的な)練習としてリンクリストにいくつかの操作を実装しようとしています。私にエラー「宣言されていない識別子の使用」を与えている型キャスト時に "宣言されていない識別子を使用する" void struct pointerへのポインタを無効にする

#include <stdlib.h> 

struct intNode_t { 
    int data; 
    struct intNode_t* next; 
}; 

int main() { 
    struct intNode_t* root = (intNode_t*) malloc(sizeof(struct intNode_t)); 
    return 0; 
} 

コンパイラ(打ち鳴らす):私は次のようにルートノードを宣言して初期化しようとしているとき、私は...しかし、非常に遠く、まだもらっていませんmallocからintNode_tへのポインタに返されたvoidポインタを型キャストしようとしているところです。私はこれがノブの質問であることを理解していますが、私は答えを他の場所で見つけることができませんでした。助言がありますか?

+0

あなたはあなたの主な機能に二回型名 '構造体intNode_t'を綴られてきました。異なる名前の 'intNode_t'の動作が異なっているのになぜ驚いていますか? –

+1

注: 'struct intNode_t *'と 'intNode_t *'は同じものではありません。少なくともCではありません。ちょうどそのタイプのキャストを削除し、あなたは(自分自身を含む)多くの人々を幸せにするでしょう。 – tofro

+1

「malloc」の結果をキャストすべきだと言った人は誰ですか?その人を聴くのをやめてください。 –

答えて

4

名前は、名前の空間から別の名前空間を占め基本的な型とtypedefの詳細については、this questionを参照してください。したがって、構造体型の名前はstruct intNode_tです。 intNode_tと呼ばれるタイプはありません。

名前はいつでもstruct intNode_tと入力するか、タイプエイリアスを作成することができます。

別々のタグ名、個別の宣言:

typedef struct foo_t_ foo_t; 

struct foo_t_ { /* ... */ }; 

これは、あなたがヘッダにタイプエイリアスを入れて、不透明なAPIタイプとして、それを公開することができます実際のコードでは、この多くの異なるパターンがあります実際の型定義を明らかにすることはありません。構造体の定義で

別々のタグ名、typedefは:

typedef struct foo_t_ { /* ... */ } foo_t; 

リユース名:

typedef struct foo_t { /* ... */ } foo_t; 

このスタイルは、ユーザーがスペルfoo_tまたはstruct foo_tについて不注意にすることができます。

は、構造体の名前を指定しないでください:

typedef struct { /* ... */ } foo_t; 

はしかし、あなたのコードでは、あなたが実際にyou should not cast the result of malloc以来、名前を繰り返し、代わりに内蔵された暗黙的に依存する必要はありません。 voidポインタからオブジェクトポインタへの変換。すでに知られている型を繰り返すべきではなく、sizeofという表現形式を使用してください。だから、欲しい:

int main() 
{ 
    struct intNode_t* root = malloc(sizeof *root); 
} 

(またreturn 0mainから暗示されていることに注意してください。)

+0

すばらしい答え。そんな丁寧な説明をしてくれてありがとう! – NiH

+0

@NiH:問題はありませんが、主なクレジットはすべての苦労をする2つのリンクされた質問に進むべきです。 –

0

名前intNode_tは、プログラムでは宣言されていません。構造体タグ名はintNode_tと宣言されています。あなたは

struct intNode_t* root = (intNode_t*) malloc(sizeof(struct intNode_t)); 
+2

また、役に立たないキャストをまったくドロップしないでください。 – alk

1

繰り返す必要を書き込むこと

は、だから、

struct intNode_t* root = (struct intNode_t*) malloc(sizeof(struct intNode_t)); 

を書く必要があるか、この場合、識別子名intNode_t次のよう

typedef struct intNode_t { 
    int data; 
    struct intNode_t* next; 
} intNode_t; 

を導入する可能性あなた自身。自分自身を繰り返さないと、エラーを減らすことができます。

struct intNode_t *root; 
root = malloc(sizeof *root); 
  • キャストが必要とされていません。 malloc()は、void*を返します。これは、すべての(関数ではない)ポインタ型と交換可能です。
  • sizeofには2つの構文バリアントがあります。sizeof(type)sizeof expression最初のサイズは()で、2番目のサイズは()です。ほとんどの人は、式(あなたのケースでは*root)が常に正しいタイプ、したがってsizeを生成するため、2番目のフォームを好む。定義+割当ては上記定義+初期化剤中に組み合わせることができる

そして、1本のライン上のすべてのフィッティング:Cにおける構造体の

struct intNode_t *root = malloc(sizeof *root); 
+0

なぜ別の宣言と割り当てがあるのですか?それは単にノイズを加え、地域を取り除くだけです。 –

+1

修正されました。 2)なぜなら初心者は宣言/定義や式/初期化子で '*'の異なる役割をしばしば混乱させるからです。 – wildplasser

関連する問題