0

我得到以下代码:

// 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();
}

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

4

2 回答 2

0

看起来你的设计是正确的,只是实施是有问题的。正如评论中提到的,你永远不应该将指针隐藏在 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 */);

外部.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 */);

内部.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 的结果。在这里击败死马:
我是否会转换 malloc 的结果?.

于 2017-03-02T14:27:23.250 回答
0

在我看来,您需要考虑的最重要的事情是,在做这样的事情时,除了变暗之外,您将一无所获,并且您想要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 *并且它们会起作用,这就是我没有 castmalloc()的返回值的原因。

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

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


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

于 2017-03-02T13:53:49.823 回答