【问题标题】:typedef opaque pointer to opaque pointertypedef opaque 指向不透明指针的指针
【发布时间】:2017-03-02 13:20:01
【问题描述】:

我得到以下代码:

// file external_module.h
typedef externaldata * externalhdl; // opaque pointer
externalhdl external_Create();

// file internal_module.h
typedef internaldata * internalhdl; // opaque pointer
internalhdl internal_Create();

我想做的是使用外部模块的不透明指针作为模块内部的不透明指针来保存不必要的分配。目前我的解决方法是:

typedef struct {externalhdl e} internaldata;

internalhdl internal_Create()
{
    internalhdl p = (internaldata*) malloc (sizeof(internaldata));
    p.e = external_Create();
    return p;
}

我想做的是使用类似的东西:

typedef ??? internaldata; //Don't know how 

internalhdl internal_Create()
{
    return external_Create();
}

从我的角度来看,这应该是可能的,因为两者都是指针,但我需要让它免费警告?感谢您的帮助。

【问题讨论】:

  • 你为什么不创建一个头文件,你可以在其中定义这个结构,并将这个文件包含到你的所有源代码中?
  • 不,你确实想要这样做!你根本不想typedef 一个对象指针!最清楚的是:永远不会 typedef 指向数据类型的指针!哦,typedef 绝对与内存分配有关。并提供minimal reproducible example。您的代码结构和问题尚不清楚。从你的表现来看,你好像迷失在你的个人typedef地狱中。
  • @betontalpfa:因为这不是 opaque 类型背后的想法。只是它不应该是typedefed 的指针。
  • 仅供参考:C 中的typedef 与其他语言的含义不同,即它不会创建新类型。它只是一个别名。您不会从类型检查中获得任何优势。
  • 我会比 Olaf 的绝妙建议走得更远。永远不要 typedef 离开指针语义。甚至函数指针 typedef 也应该是函数 typedef,变量声明为指向它们的指针。

标签: c pointers typedef opaque-pointers


【解决方案1】:

在我看来,您需要考虑的最重要的事情是,在做这样的事情时,除了变暗之外,您将一无所获,并且您希望 typedef 指向另一种类型的指针。如果它是一个不透明的指针,那么typedef 它也没有意义,因为你永远不会访问底层结构的成员,它很可能作为void * 指针传递,但是当你分配它时,您必须知道它的类型,因为编译器需要知道它的大小和布局才能正确分配它(例如,正确对齐它是不可能的)。

如果您不想重复使用sizeof 运算符来分配正确的大小,有两种可能的方法1

  1. 使用宏

    #define allocate(x) x = malloc(sizeof(*x))
    

    然后

    my_type *x;
    allocate(x);
    

    但这是可怕的和不清楚的。

  2. 使用分配函数,

    my_type *
    my_type_alloc()
    {
        return malloc(sizeof(my_type));
    }
    

    这样

    my_type *x;
    x = my_type_allocate();
    

    这是干净和简单的,你不能做错。

请注意,返回适当的指针类型只是确保您不会意外地做一些可能导致未定义行为的事情,但是分配函数可以简单地返回 void * 并且它们会起作用,这就是我没有强制转换 malloc() 的原因s 返回值。

语法糖是您必须非常小心的东西,因为有时看起来您简化和改进了语法,而您所做的是向将阅读您的代码的其他程序员隐藏重要信息,该程序员甚至可能是您自己编写代码后的时间。

而您的解决方法实际上导致了一次不必要的分配。事实上,当您最终了解指针时,您将真正避免不必要的分配,因为您只读取数据时不复制数据。


1在这两种情况下,您都应该在分配完成后检查NULL,以确保您可以访问此类指针而不会导致未定义的行为

【讨论】:

    【解决方案2】:

    您的设计似乎走在了正确的轨道上,只是实施存在问题。正如 cmets 中提到的,您永远不应该将指针隐藏在 typedef 后面,不透明指针也不例外。如果调用者认为这些是分配的变量,他们可能会决定做如下愚蠢的事情:

    set_obj(obj1, "foo"); // set private data to something
    memcpy(&obj2, &obj1); // take a hardcopy of the data (or so we thought)
    set_obj(obj1, "bar"); // set private data to something else
    print_obj(obj2);      // prints "bar", wtf!!!
    

    所以停止隐藏指针。 稍作修改,您应该可以让代码按预期工作:

    外部.h

    typedef struct external_t external_t;
    
    external_t* external_create (/* parameters here */);
    

    external.c

    #include "external.h"
    
    external_t* external_create (/* parameters here */)
    {
      external_t* ext = malloc(sizeof *ext);
      /* initialize stuff here */
      return ext;
    }
    

    内部.h

    #include "external.h"
    
    typedef struct internal_t internal_t;
    
    internal_t* internal_create (/* parameters here */);
    

    internal.c

    #include "internal.h"
    
    struct internal_t
    {
      external_t* ext;
    };
    
    internal_t* internal_create (/* parameters here */)
    {
      internal_t* inter = malloc(sizeof *inter);
      inter->ext = external_create (/* parameters here */);
      if(inter->ext == NULL)
      {
        return NULL;
      }
      /* initialize stuff here */
      return inter;
    }
    

    调用者也必须使用指针。


    另外,不需要强制转换 malloc 的结果。在这里打死马:
    Do I cast the result of malloc?.

    【讨论】:

      猜你喜欢
      • 2011-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-30
      相关资源
      最近更新 更多