dereferencing pointer to incomplete type

作者:fly 发布于:2015-1-14 17:51 分类:Linux

   在linux下编程,抑或在windows下使用gcc命令编译程序,常会遇到典型的linux c错误dereferencing pointer to incomplete type。

   一般情况下,此错误与结构体的定义有关。

   linux下较标准的结构体定义方法为:

   struct Node {

       DataType info;

       struct Node *link;

   };

   较多的程序员喜欢用typedef,如下定义:

   typedef struct Node {

       DataType info;

       struct Node *link;

   }Node;

   两者的不同之处在于,前者在所有定义新Node对象时,需如此定义:

   struct Node* p = (struct Node*)malloc(sizeof(struct Node));

   后者则可以:

   Node *p = (Node *)malloc(sizeof(Node));

   即可以将Node替代struct Node(因为取了别名的关系)。

   还有一种我们常见到的情况,看有关linux内核的书时,会经常看到类似这种写法的函数:

   void (* open)(struct vm_area_struct *area);瞬间蛋疼,又是回调函数又是结构体参数,关键是还不能简写!而这种,也是没有用typedef的正规写法。

   根据Linux下的编码规范,typedef在绝大多数情况下都是禁止使用的,他们只在以下情况下被允许使用:

(a) 完全不透明的对象(这种情况下要主动使用typedef来隐藏这个对象实际上是什么)。例如:“pte_t”等不透明对象,你只能用合适的访问函数来访问它们。注意!不透明性和“访问函数”本身是不好的。我们使用pte_t等类型的原因在于真的是完全没有任何共用的可访问信息。

 (b) 清楚的整数类型,如此,这层抽象就可以帮助消除到底是“int”还是“long”的混淆。u8/u16/u32是完全没有问题的typedef,不过它们更符合类别(d)而不是这里。再次注意!要这样做,必须事出有因。如果某个变量是“unsigned long“,那么没有必要typedef unsigned long myflags_t;不过如果有一个明确的原因,比如它在某种情况下可能会是一个“unsigned int”而在其他情况下可能为“unsigned long”,那么就不要犹豫,请务必使用typedef。

(c) 当你使用sparse按字面的创建一个新类型来做类型检查的时候。

(d) 和标准C99类型相同的类型,在某些例外的情况下。虽然让眼睛和脑筋来适应新的标准类型比如“uint32_t”不需要花很多时间,可是有些人仍然拒绝使用它们。因此,Linux特有的等同于标准类型的“u8/u16/u32/u64”类型和它们的有符号类型是被允许的——尽管在你自己的新代码中,它们不是强制要求要使用的。当编辑已经使用了某个类型集的已有代码时,你应该遵循那些代码中已经做出的选择。

(e) 可以在用户空间安全使用的类型。在某些用户空间可见的结构体里,我们不能要求C99类型而且不能用上面提到的“u32”类型。因此,我们在与用户空间共享的所有结构体中使用__u32和类似的类型。

发表评论:

 
Powered by emlog sitemap