質問

私はこれについて多くの質問を見てきましたが、特定のコードなしでは別の方法で質問をするつもりです。方法はありますか 簡単に タイプが不完全になっている原因を判断する?私の場合、私は誰かのエルゼスコードを使用していますが、ヘッダーが正しくないことは完全に確信していますが、(コンピューターは人間の眼球よりもはるかに速く、より良いことをするので)コンパイラに言う方法があります、 "ねえ 考える 34行目にタイプXがありますが、実際には ない」エラー自体は、割り当てられたときにのみ表示されますが、これはあまり役に立ちません。

役に立ちましたか?

解決

先日、誰かが誤って不完全なタイプを使用して、ようなものを指定することで質問を見ました。

struct a {
    int q; 
}; 
struct A *x; 
x->q = 3;

コンパイラはそれを知っていました struct A それにもかかわらず、構造体でした A のおかげで、完全に定義されていない struct キーワード。

それはC ++で、そのような使用法 struct 非定型です(そして、結局のところ、フットシューティングにつながる可能性があります)。あなたがそうするならcで

typedef struct a {
    ...
} a;

その後、使用できます a Typenameとして、省略します struct 後で。これにより、コンパイラは、名前を間違えたり、ヘッダーを忘れたりする場合、不完全なタイプではなく、未定義の識別子エラーを後で提供します。

他のヒント

別の考えられる理由は、間接的な参照です。コードが現在のCファイルに含まれていない構造体に言及している場合、コンパイラは文句を言います。

a-> b-> c // b bが現在のcファイルに含まれていない場合エラー

どういう意味ですか、エラーが割り当てたときにのみ表示されますか?たとえば、GCCでは、課題が見えない:

int main() {
    struct blah *b = 0;
    *b; // this is line 6
}

incompletetype.c:6: error: dereferencing pointer to incomplete type.

エラー 6行目では、完全なタイプであるかのように不完全なタイプを使用しました。それまでは元気でした。

間違いは、タイプを定義するヘッダーを含める必要があることです。しかし、コンパイラは、関数の外側の任意の行に含まれるべき行を推測することはできません。また、システム上のすべてのテキストファイルをトロールして、それを定義するヘッダーを探して、それを含めることを提案することもありません。

あるいは(良い点、ポタトスワッター)、エラーは行にあります。 b あなたが定義されました 意味した 実際に存在するが実際に指定されたいくつかのタイプを指定するには blah. 。変数の定義を見つける b ほとんどの場合、それほど難しくないはずです。 Idesは通常あなたのためにそれを行うことができます、コンパイラ警告は気になることはないかもしれません。ただし、使用しているものの定義が見つからない場合は、かなり凶悪なコードです。

何が問題なのか正確にはわかりません。不完全なタイプは、「欠落している」タイプではありません。無能なタイプはタイプです 宣言されています だがしかし 定義されています (structタイプの場合)。非定義宣言を見つけるのは簡単です。不足している定義を見つけることに関しては...コンパイラはここであなたを助けません。それがそもそもエラーの原因だからです。

Cのタイプの誤りの不完全な理由は、タイプ名のタイプミスです。これにより、コンパイラが一方の名前を他の名前に一致させることができなくなります(宣言を定義に一致させるなど)。しかし、繰り返しますが、コンパイラはここであなたを助けることはできません。コンパイラはタイプミスについて推測しないでください。

通常、このエラーは、構造体の名前がコード内の構造体の初期化と異なるかどうかを示しているため、通常、cはあなたが置く構造体の名前を見つけ、元の構造体が見つからない場合、これは通常表示されるか、または表示されるか、またはそのポインターに向けられたポインターを指すと、エラーが表示されます。

解決策

C言語について話すと、宣言コードに従うことが解決策になることを明らかにしました。

typedef struct ListNode
{
    int data;
    ListNode * prev;
    ListNode * next;
} ListNode;

したがって、一般的なルールとして、私はタイプ定義とstructの名前の両方に対して同じ名前を付けます。

typedef struct X
{
    // code for additional types here
    X* prev; // reference to pointer
    X* next; // reference to pointer
} X;

B-問題のあるサンプル

次の宣言は、両方によって不完全であると見なされます gcc 次のステートメントを実行するときのコンパイラ。 ;

removed->next->prev = removed->prev;

また、エラー出力で報告された逆効果コードについて同じエラーが発生します。

>gcc Main.c LinkedList.c -o Main.exe -w
LinkedList.c: In function 'removeFromList':
LinkedList.c:166:18: error: dereferencing pointer to incomplete type 'struct ListNode'
     removed->next->prev = removed->prev;

両方のために ヘッダーファイル 以下にリストされている宣言。

typedef struct
{
    int data;
    ListNode * prev;
    ListNode * next;
} ListNode;

さらに、これ。

typedef struct ListNodeType
{
    int data;
    ListNode * prev;
    ListNode * next;
} ListNode;

プログラム全体の最適化を含む可能なシナリオ以外では、次のようなものに対して生成されたコードコードは次のように生成されました。

struct foo *bar;
struct foo *test(struct foo *whatever, int blah)
{
  return blah ? whatever: bar;
}

どのメンバーによって完全に影響を受けません struct foo 含まれる可能性があります。 Makeユーティリティは一般に、構造の完全な定義が表示されるコンパイルユニットを再コンパイルするため、そのような変更が実際に生成されたコードに実際に影響を与えることができなかった場合でも、実際には必要ないコンピレーションユニットから完全な構造定義を省略することが一般的です彼ら、そしてそのような省略は一般に警告に値しません。

コンパイラには、自動または静的な期間でタイプの宣言オブジェクトを処理する方法、タイプのメンバーを含む集合体の宣言、または構造またはユニオンのメンバーにアクセスするコードを扱う方法を知るために、完全な構造または組合定義が必要です。コンパイラが上記の操作のいずれかを実行するために必要な情報を持っていない場合、それについてスクワークする以外に選択肢はありません。

ちなみに、標準では、コンパイラが完全な組合定義を表示することを要求できるが、診断を必要としない場合、もう1つの状況があります。構造タイプの1つのポインターを使用してその一般的な初期シーケンスのメンバーを検査する処理コードは、そのようなコードが他のタイプの構造の対応するメンバーにアクセスしている可能性があることを認識するために必要です。完全な組合タイプが表示されているが、そうではない場合は標準に準拠している場合、どのコンパイラが標準に準拠している場合は、どちらの場合も、いずれの場合も非変性コードを生成する傾向があります。 -fno-strict-aliasing フラグが使用されます。この場合、両方の場合に適合コードが生成されます]しかし、適合コンパイラの正しい動作を保証するような方法でCISルールを使用するコードを書きたい場合、完全な組合タイプを確保する必要があるかもしれません定義が表示されます。そうしないと、コンパイラが静かに偽のコードを生成する可能性があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top