解除指向不完整types的指针

我已经看到了很多关于这个问题的问题,但是我会以不同的方式提出问题。 是否有一种方法容易确定是什么导致types不完整? 在我的情况下,我正在使用别人的代码,我完全相信我没有正确的标题,但(因为电脑做这个东西比人眼更快,更好)有没有办法让编译器说,“嘿,你认为你在第34行input了X,但实际上是缺less的 。 错误本身只在您分配时显示,这不是很有帮助。

有一天我看到一个问题,有人不小心使用了一个不完整的types,通过指定类似struct a { int q; }; struct A *x; x->q = 3; struct a { int q; }; struct A *x; x->q = 3; 。 编译器知道struct A是一个结构体,尽pipeA完全没有定义,依靠struct关键字。

这是在C ++中,这种struct使用是非典型的(事实certificate,可以导致足迹)。 在C中,如果你这样做

 typedef struct a { ... } a; 

那么你可以使用a作为types名称,稍后省略struct 。 这会导致编译器稍后给你一个未定义的标识符错误,而不是不完整的types,如果你输错了名字或忘记了一个头文件。

你是什​​么意思,错误只显示当你分配? 例如在GCC上,看不到任务:

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

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

错误在第6行,这就是我使用不完整的types,就好像它是一个完整的types。 直到那时我还好。

错误的是你应该包含任何头文件定义的types。 但是编译器不可能猜到应该包含哪些行:函数外部的任何行都可以。 它也不会去浏览你的系统上的每个文本文件,寻找一个定义它的头文件,并且build议你应该包含它。

或者(好点,potatoswatter),错误是在b被定义的那一行,当你打算指定一些实际存在的types,但实际上指定了blah 。 在大多数情况下,findvariablesb的定义不应该太困难。 IDE通常可以为你做,编译器警告也许不会被打扰。 但是,如果你找不到你正在使用的东西的定义,这是一些非常令人讨厌的代码。

我不完全明白是什么问题。 不完整的types不是“缺less”的types。 Incompetetypes是一个声明未定义的types(在结构types的情况下)。 find非定义的声明很容易。 至于发现缺失的定义…编译器不会帮你在这里,因为这是什么原因造成的错误。

C中不完整types错误的一个主要原因是types名称中的拼写错误,这会阻止编译器将一个名称与另一个名称进行匹配(如将声明与定义相匹配)。 但再次,编译器不能帮你在这里。 编译器不要对拼写错误进行猜测。

另一个可能的原因是间接引用。 如果代码引用了当前c文件中没有包含的结构,编译器会报错。

a-> b-> c //如果b不包含在当前c文件中,则会出错

这个错误通常表明,如果你的结构体的名字不同于你的结构体在代码中的初始化,那么通常情况下,c会find你放置的结构体的名字,如果找不到原始结构体,通常会出现如果您将指针指向该指针,则会显示错误。

一个办法

说到C语言,我刚刚发现,下面的声明代码将是解决scheme;

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

所以作为一般规则,我为结构的types定义和名称都给出了相同的名字;

 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可能包含哪些成员struct foo影响。 由于make实用程序通常会重新编译出现结构完整定义的任何编译单元,即使此类更改实际上不会影响为其生成的代码,通常也会忽略编译单元中完全不需要的完整结构定义他们,这样的疏忽一般不值得警惕。

编译器需要有一个完整的结构或联合定义来知道如何处理自动或静态持续types的声明对象,包含types成员的聚合声明或访问结构或联合成员的代码。 如果编译器不具备执行上述操作之一所需的信息,那么它将别无select,只能重复一遍。

顺便说一下,还有一种情况是,标准允许编译器要求一个完整的联合定义可见,但不需要诊断:如果两个结构以Common Initial Sequence开始,并且包含两个联合的联合types在编译器时是可见的正在处理的代码使用其中一个结构types的指针来检查该公共初始序列的成员,编译器需要认识到这样的代码可能正在访问另一个types的结构的相应成员。 我不知道什么编译器,如果任何符合标准的时候,完整的联合types是可见的,但不是当[gcc很容易产生不符合的代码,除非-fno-strict-aliasing标志是在这种情况下,它将在这两种情况下生成符合的代码],但是如果要编写使用CIS规则的代码,以保证符合编译器的正确行为,则可能需要确保完整的联合types定义是可见; 不这样做可能会导致编译器自动生成伪代码。