我已经看到了很多问题,但是我将在没有特定代码的情况下以不同的方式提出这个问题。有没有一种方式 容易地 确定导致类型不完整的是什么?就我而言,我正在使用Elses代码,并且完全确定我没有正确的标题,但是(因为计算机比人类眼球更快,更好)是否可以让编译器说, “嘿,你 思考 您在第34行中有X型X,但实际上是 失踪。”错误本身仅在您分配时出现,这不是很有帮助。

有帮助吗?

解决方案

前几天,我看到了一个问题,有人通过指定类型来无意中使用了不完整的类型

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

编译器知道 struct A 是一个结构,尽管 A 完全不确定,凭借 struct 关键词。

那是在C ++中,这样的用法 struct 是非典型的(事实证明,可以导致脚步)。在C中,如果您这样做

typedef struct a {
    ...
} a;

那你可以使用 a 作为打字机并省略 struct 之后。这将导致编译器以后为您提供未定义的标识符错误,而不是不完整的类型,如果您误解了名称或忘记标题。

其他提示

另一个可能的原因是间接参考。如果代码引用当前C文件中未包含的结构,则编译器将抱怨。

A-> b-> c //如果当前C文件中未包含B

您是什么意思,只有分配时出现错误?例如,在GCC上,看不到分配:

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

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

错误 在第6行,我使用了不完整的类型,就好像它是完整的类型一样。直到那时我都很好。

错误是您应该包含任何定义类型的标题。但是编译器不可能猜测应该在以下方面包含哪一条线:函数以外的任何行都可以,几乎可以。它也不会拖到系统上的每个文本文件,寻找定义它的标题,并建议您将其包括在内。

或者(好点,potatoswatter),错误是在线 b 被定义,当你 意思是 指定实际存在但实际指定的类型 blah. 。查找变量的定义 b 在大多数情况下,不应该太困难。 IDE通常可以为您做,编译器警告可能不会被打扰。但是,如果您找不到您使用的内容的定义,这是一些令人发指的代码。

我不完全了解问题所在。不完整的类型不是“丢失”的类型。无能的类型是一种类型 宣布 但不是 定义 (如果结构类型)。找到非定义声明很容易。至于找到缺失的定义...编译器在这里无法为您提供帮助,因为这首先是导致错误的原因。

C中不完整类型错误的主要原因是类型名称中的错别字,这阻止编译器将一个名称与另一个名称匹配(例如将声明与定义匹配)。但是,编译器再次无法帮助您。编译器不会对错别字进行猜测。

此错误通常显示您的结构的名称是否与代码中结构的初始化不同,因此通常,C会找到您放置的结构的名称,如果找不到原始结构,通常会出现,或如果指向指针指向该指针,则会出现错误。

一个解法

对C语言说话,我刚刚发现,以下声明代码将成为解决方案。

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

因此,作为一般规则,我同时给出结构的类型定义和名称相同的名称。

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 可能包含。因为制造实用程序通常会重新编译任何结构的完整定义的编译单元,即使这种更改实际上无法影响为它们生成的代码,也很常见省略从不需要实际不需要的编译单元中省略完整的结构定义他们,而且这种遗漏通常不值得警告。

编译器需要具有完整的结构或联合定义,以了解如何处理具有自动或静态持续时间的类型的声明对象,包含类型成员的聚合的声明或访问结构或联合成员的代码。如果编译器没有执行上述操作之一所需的信息,那么它别无选择,只能对其进行调整。

顺便说一句,在某种情况下,标准将允许编译器需要可见完整的联合定义,但不需要诊断:如果两个结构以共同的初始序列开头,并且在编译器时可见包含两者的联合类型正在处理使用其中一种结构类型的指针来检查该公共初始序列的成员,需要编译器来识别该代码可能正在访问其他类型的结构的相应成员。我不知道当可见完整的联合类型时是否符合标准,但在不符合标准的情况下,我不知道哪种编译器在不符合标准的情况 -fno-strict-aliasing 使用标志,在这种情况下,它将在两种情况下都会生成符合代码]]但是,如果要以一种方式编写使用CIS规则的代码,以确保正确的编译器上的正确行为,则可能需要确保完整的联合类型定义是可见的;否则可能会导致编译器默默生成伪造代码。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top