便于“取消指向”指针typedef的方法?

时间:2010-11-09 15:52:42

标签: c typedef typeof

遗憾的是,这在某些外部库中定义:无法触摸!

// library.h
typedef struct {
    long foo;
    char *bar;
   /* ... (long & complex stuff omitted) */
} *pointer_to_complex_struct_t;

现在问题:如何声明 complex_struct_t 变量?

  • 理想的解决方案,但不允许! (不能更改外部库):

    // library.h
      /* ... (long & complex stuff omitted) */
    } complex_struct_t, *pointer_to_complex_struct_t;
    
    
    // my.h
    extern complex_struct_t my_variable;
    
  • 非便携式解决方案(gcc):

    // my.h
    extern typeof( * (type_placeholder)0 )  my_variable; // Thanks caf!
    
  • 其他?更好?谢谢!

奖金问题:函数指针的相同问题(如果有任何差异;我对此表示怀疑)。


ADDED奖励:下面是完全相同的问题,但功能而不是结构。这不应该对简短的回答(“号码”)产生任何影响,这是我最初感兴趣的唯一答案。我没想到有些人会因为创造性的解决方法而知道并完成工作,这就是为什么我简化了从函数到结构的问题(函数指针具有特殊的隐式转换规则,以方便混淆)。但是,嘿,为什么不呢?让我们开始复制粘贴解决方案竞赛。一些解决方法可能比其他解决方案更好。

///// library.h //////
// Signature has been simplified
typedef double (*ptr_to_callback_t)(long, int, char *);
// Too bad this is not provided: typedef double callback_t(long, int, char *);

///// my.h /////
// This avoids copy-paste but is not portable
typedef typeof( * (ptr_to_callback_t)0 ) callback_t;

extern callback_t callback_1;
extern callback_t callback_2;
extern callback_t callback_3;
// etc.

简短回答=否,目前没有typeof

的便携式替代品

基本的复制粘贴解决方法适用于功能但不适用于结构。编译器将匹配重复的函数类型,但不会关联重复的结构类型:需要强制转换,并且重复的结构类型将在没有编译警告的情况下发散。

4 个答案:

答案 0 :(得分:2)

不,不幸的是你不能用标准的C做。使用C ++,一个简单的元函数可以做到这一点。

但是你可以复制粘贴结构的定义,从而保留原始的

typedef struct {
 ///same  struct
} complex_struct_t;

此解决方案的缺点是表达式&complex_struct_t不是pointer_to_complex_struct_t类型,而是指向未命名struct {//your members}的类型指针; 如果你需要这个功能,你需要reinterpret_casting ...

答案 1 :(得分:1)

如上所述,你的问题的答案是“不”;如果您拥有的是

的类型定义
typedef struct {...} *ptr_to_struct;

然后没有(标准的,可移植的)方式来提取结构类型。如果您必须创建结构的实例,那么您将能够做的最好的是

ptr_to_struct s = malloc(sizeof *s);

然后使用->组件选择运算符(或通过解除引用s并使用.运算符引用结构中的字段,但您不希望这样做)。

你问过同样的事情是否适用于函数指针;你真的需要说出你的意思。如果你有像

这样的情况
typedef struct {...} *ptr_to_struct;
ptr_to_struct foo() {...}
那么情况就像上面那样;你没有办法声明那种类型的变量。

答案 2 :(得分:0)

制作头文件的本地副本并包含它而不是原始文件。现在你可以做任何你想做的事。如果这个库可以更改(更新或其他任何东西),你可以编写一个小脚本来自动执行这些步骤,并在编译时从makefile中调用它。只需确保不要盲目地粘贴到标题中,搜索特定行(} *pointer_to_complex_struct_t;)并在不再找到时抛出错误。

如果此标头使用此库的其他标头,则可能必须对包含的搜索路径保持谨慎。另外,如果其他标题包含了包含的顺序。

编辑(为评论中提到的真实目标):你不能用函数指针来做这件事。只需使用typedef的签名编写所需的函数,它就会与指针兼容并可以被它调用。

答案 3 :(得分:0)

怎么样:

pointer_to_complex_struct_t newStruct ( void ) {
    pointer_to_complex_struct_t ptr = 
         (pointer_to_complex_struct_t) malloc ( sizeof (*pointer_to_complex_struct_t) );
    return ptr;
}

你必须通过ptr->引用你新创建的结构;但你可以创造新的。

当然,这可能会也可能不会起作用,具体取决于结构的实际使用方式。想到的例子是:如果结构以

结尾,该怎么办?
char data[0];

并且数据用于指向结构后面的内存。