C语言 解引用指向不完整类型的指针
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2700646/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
dereferencing pointer to incomplete type
提问by nick
I've seen a lot of questions on this but I'm going to ask the question differently without specific code. Is there a way of EASILYdetermining what is causing the type to be incomplete? In my case I'm using someone elses code and I'm completely sure I don't have the headers right, but (since computers do this stuff much faster and better than human eyeballs) is there a way to get the compiler to say, "hey you thinkyou have type X at line 34 but that's actually missing." The error itself only shows up when you assign, which isn't very helpful.
我已经看到很多关于此的问题,但我将在没有特定代码的情况下提出不同的问题。有没有一种方法可以轻松确定导致类型不完整的原因?在我的情况下,我使用的是别人的代码,我完全确定我没有正确的标题,但是(因为计算机比人类眼球更快更好地完成这些事情)有没有办法让编译器说,“嘿,您认为您在第 34 行输入了 X,但实际上缺少它。” 错误本身仅在您分配时显示,这不是很有帮助。
采纳答案by Potatoswatter
I saw a question the other day where someone inadvertently used an incomplete type by specifying something like
前几天我看到一个问题,有人通过指定类似的东西无意中使用了不完整的类型
struct a {
int q;
};
struct A *x;
x->q = 3;
The compiler knew that struct Awas a struct, despite Abeing totally undefined, by virtue of the structkeyword.
struct A尽管A完全未定义,但编译器通过struct关键字知道这是一个结构体。
That was in C++, where such usage of structis atypical (and, it turns out, can lead to foot-shooting). In C if you do
那是在 C++ 中,这种用法struct是不典型的(而且,事实证明,会导致脚射门)。在 C 中,如果你这样做
typedef struct a {
...
} a;
then you can use aas the typename and omit the structlater. This will lead the compiler to give you an undefined identifier error later, rather than incomplete type, if you mistype the name or forget a header.
那么您可以使用a作为类型名并省略struct后者。如果您输入错误名称或忘记标头,这将导致编译器稍后为您提供未定义的标识符错误,而不是不完整的类型。
回答by Steeven Li
Another possible reason is indirect reference. If a code references to a struct that not included in current c file, the compiler will complain.
另一个可能的原因是间接引用。如果代码引用了当前 c 文件中未包含的结构,编译器会报错。
a->b->c //error if b not included in current c file
a->b->c //如果当前c文件中不包含b则出错
回答by Steve Jessop
What do you mean, the error only shows up when you assign? For example on GCC, with no assignment in sight:
你是什么意思,错误只在你分配时出现?例如在 GCC 上,看不到任何分配:
int main() {
struct blah *b = 0;
*b; // this is line 6
}
incompletetype.c:6: error: dereferencing pointer to incomplete type.
incompletetype.c:6: error: dereferencing pointer to incomplete type.
The error isat line 6, that's where I used an incomplete type as if it were a complete type. I was fine up until then.
该错误是在第6行,这就是我用了一个不完整的类型,就好像它是一个完整的类型。直到那时我都很好。
The mistake is that you should have included whatever header defines the type. But the compiler can't possibly guess what line that should have been included at: any line outside of a function would be fine, pretty much. Neither is it going to go trawling through every text file on your system, looking for a header that defines it, and suggest you should include that.
错误在于您应该包含定义类型的任何标头。但是编译器不可能猜测应该包含在哪一行:函数之外的任何行都可以,几乎。它也不会遍历系统上的每个文本文件,寻找定义它的标题,并建议您应该包含它。
Alternatively (good point, potatoswatter), the error is at the line where bwas defined, when you meantto specify some type which actually exists, but actually specified blah. Finding the definition of the variable bshouldn't be too difficult in most cases. IDEs can usually do it for you, compiler warnings maybe can't be bothered. It's some pretty heinous code, though, if you can't find the definitions of the things you're using.
或者(好点,potatoswatter),错误出现在b定义的行上,当您打算指定某种实际存在但实际上指定的类型时blah。b在大多数情况下,找到变量的定义应该不会太困难。IDE 通常可以为您完成,编译器警告可能不会被打扰。但是,如果您找不到正在使用的事物的定义,那么这是一些非常令人发指的代码。
回答by AnT
I don't exactly understand what's the problem. Incomplete type is not the type that's "missing". Incompete type is a type that is declaredbut not defined(in case of struct types). To find the non-defining declaration is easy. As for the finding the missing definition... the compiler won't help you here, since that is what caused the error in the first place.
我不完全明白是什么问题。不完整的类型不是“缺失”的类型。不竞争类型是已声明但未定义的类型(在结构类型的情况下)。找到非定义声明很容易。至于找到丢失的定义......编译器不会在这里帮助你,因为这首先是导致错误的原因。
A major reason for incomplete type errors in C are typos in type names, which prevent the compiler from matching one name to the other (like in matching the declaration to the definition). But again, the compiler cannot help you here. Compiler don't make guesses about typos.
C 中不完整类型错误的一个主要原因是类型名称中的拼写错误,这会阻止编译器将一个名称与另一个名称匹配(例如将声明与定义匹配)。但同样,编译器在这里也帮不了你。编译器不会对拼写错误进行猜测。
回答by catzilla_waw
this error usually shows if the name of your struct is different from the initialization of your struct in the code, so normally, c will find the name of the struct you put and if the original struct is not found, this would usually appear, or if you point a pointer pointed into that pointer, the error will show up.
此错误通常显示您的结构名称是否与代码中结构的初始化不同,因此通常,c 会找到您放置的结构名称,如果找不到原始结构,通常会出现这种情况,或者如果您指向指向该指针的指针,则会显示错误。
回答by Levent Divilioglu
A - Solution
一个办法
Speaking for C language, I've just found ampirically that following declaration code will be the solution;
说到 C 语言,我刚刚发现以下声明代码将是解决方案;
typedef struct ListNode
{
int data;
ListNode * prev;
ListNode * next;
} ListNode;
So as a general rule, I give the same name both for both type definition and name of the struct;
因此,作为一般规则,我为结构的类型定义和名称赋予相同的名称;
typedef struct X
{
// code for additional types here
X* prev; // reference to pointer
X* next; // reference to pointer
} X;
B - Problemetic Samples
B - 有问题的样品
Where following declarations are considered both incomplete by the gcccompiler when executing following statement. ;
在gcc执行以下语句时,编译器认为以下声明都不完整。;
removed->next->prev = removed->prev;
And I get same error for the dereferencing code reported in the error output;
对于错误输出中报告的取消引用代码,我得到了同样的错误;
>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;
For both of the header filedeclarations listed below;
对于下面列出的两个头文件声明;
typedef struct
{
int data;
ListNode * prev;
ListNode * next;
} ListNode;
Plus this one;
再加上这个;
typedef struct ListNodeType
{
int data;
ListNode * prev;
ListNode * next;
} ListNode;
回答by supercat
Outside of possible scenarios involving whole-program optimization, the code code generated for something like:
在涉及整个程序优化的可能场景之外,生成的代码代码如下:
struct foo *bar;
struct foo *test(struct foo *whatever, int blah)
{
return blah ? whatever: bar;
}
will be totally unaffected by what members struct foomight contain. Because make utilities will generally recompile any compilation unit in which the complete definition of a structure appears, even when such changes couldn't actually affect the code generated for them, it's common to omit complete structure definitions from compilation units that don't actually need them, and such omission is generally not worthy of a warning.
将完全不受成员struct foo可能包含的内容的影响。因为 make 实用程序通常会重新编译出现完整结构定义的任何编译单元,即使此类更改实际上不会影响为它们生成的代码,所以通常会从实际上不需要的编译单元中省略完整的结构定义他们,而这种遗漏一般不值得警告。
A compiler needs to have a complete structure or union definition to know how to handle declarations objects of the type with automatic or static duration, declarations of aggregates containing members of the type, or code which accesses members of the structure or union. If the compiler doesn't have the information needed to perform one of the above operations, it will have no choice but to squawk about it.
编译器需要有完整的结构或联合定义,以了解如何处理具有自动或静态持续时间的类型的声明对象、包含该类型成员的聚合声明或访问结构或联合成员的代码。如果编译器没有执行上述操作之一所需的信息,它将别无选择,只能大声疾呼。
Incidentally, there's one more situation where the Standard would allow a compiler to require a complete union definition to be visible but would not require a diagnostic: if two structures start with a Common Initial Sequence, and a union type containing both is visible when the compiler is processing code that uses a pointer of one of the structure types to inspects a member of that Common Initial Sequence, the compiler is required to recognize that such code might be accessing the corresponding member of a structure of the other type. I don't know what compilers if any comply with the Standard when the complete union type is visible but not when it isn't [gcc is prone to generate non-conforming code in either case unless the -fno-strict-aliasingflag is used, in which case it will generate conforming code in both cases] but if one wants to write code that uses the CIS rule in such a fashion as to guarantee correct behavior on conforming compilers, one may need to ensure that complete union type definition is visible; failure to do so may result in a compiler silently generating bogus code.
顺便说一句,还有一种情况,标准允许编译器要求完整的联合定义可见但不需要诊断:如果两个结构以公共初始序列开头,并且当编译器可以看到包含两者的联合类型时正在处理使用一种结构类型的指针来检查该公共初始序列的成员的代码,编译器需要识别此类代码可能正在访问其他类型的结构的相应成员。我不知道当完整的联合类型可见时哪些编译器符合标准,但在不可见时则不然 [gcc 在任何一种情况下都容易生成不符合标准的代码,除非-fno-strict-aliasing标志被使用,在这种情况下它会在两种情况下生成一致的代码]但是如果一个人想要编写使用 CIS 规则的代码,以保证在一致编译器上的正确行为,则可能需要确保完整的联合类型定义可见;不这样做可能会导致编译器默默地生成虚假代码。

