简体   繁体   English

typedef指向不透明指针的不透明指针

[英]typedef opaque pointer to opaque pointer

I got the following code: 我得到以下代码:

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

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

What i would like to do is to use an opaque pointer of a external module as a opaque pointer inside of my module to save unessasary allocs. 我想做的是将外部模块的不透明指针用作模块内部的不透明指针,以保存非文字分配。 Currently my workaround implimentation is: 目前,我的解决方法是:

typedef struct {externalhdl e} internaldata;

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

What I would like to do is use something like: 我想做的是使用类似:

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

internalhdl internal_Create()
{
    return external_Create();
}

From my point of view it should be possible since both are pointer but I need to get it warning free? 从我的角度来看,这是有可能的,因为两者都是指针,但是我需要使其免受警告吗? Thanks for your help. 谢谢你的帮助。

The most important thing you need to consider in my opinion, is that you will gain absolutely nothing but darkenss in doing something like this, and that you want to typedef a pointer to another type of pointer. 在我看来,您需要考虑的最重要的事情是,这样做绝对会让您一无所获,但是会使您的工作变得更加黑暗,并且您想将一个typedef指针定义为另一种类型的指针。 If it is an opaque poitner, it doesn't make sense to typedef it also because you will never access the members of the underlying structure, it might very well be passed as a void * pointer, but when you allocate it, you MUST know it's type because the compiler needs to know it's size and layout in order to allocate it correctly ( aligning it correctly for example would be impossible otherwise ). 如果它是不透明的Poitner,则对它进行typedef也没有意义,因为您将永远不会访问基础结构的成员,它很可能作为void *指针传递,但是在分配它时,您必须知道之所以使用这种类型,是因为编译器需要知道它的大小和布局才能正确分配它( 例如,否则无法正确对齐 )。

If you don't want to repeatedly use the sizeof operator to allocate the correct size there are two possible approaches 1 如果您不想重复使用sizeof运算符来分配正确的大小,则有两种可能的方法1

  1. Use a macro 使用宏

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

    and then 接着

     my_type *x; allocate(x); 

    but this is horrible and unclear. 但这是可怕的和不清楚的。

  2. Use an allocation function, 使用分配功能,

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

    such that 这样

     my_type *x; x = my_type_allocate(); 

    this is clean and simple, and you can't do it wrong. 这是干净而简单的,您不会做错。

Note that returning the appropriate pointer type just ensures that you will not accidentally do something that might cause undefined behavior, but allocation functions can simply return void * and they will work, that is why I did not cast malloc() 's return value. 请注意,返回适当的指针类型只是确保您不会意外地执行可能导致未定义行为的操作,但是分配函数可以简单地返回void *并且它们可以工作,这就是为什么我没有转换malloc()的返回值。

Syntax sugar is something that you must be very careful with, because somtimes it looks like you simplified and improved syntax when what you did was hide vital information from the fellow programmer that will read your code, that programmer could even be yourself some time after writing the code. 语法糖是您必须非常小心的事情,因为当您所做的事情是隐藏对将要读取您的代码的程序员的重要信息时,有时看起来好像您简化了语法并改进了语法,程序员甚至可能在写完代码后就成为自己了编码。

And your workaround is actually causing one unecessary allocation. 您的解决方法实际上导致了不必要的分配。 In fact, when you finally understand poitners, you will then really avoid unnecessary allocations by not copying data when you will only read from it. 实际上,当您最终了解了Poitners之后,您便会在仅从中读取数据时不复制数据,从而真正避免了不必要的分配。


1 In both cases, you should check for NULL after the allocation is performed to ensure you can access such pointer without causing undefined behavior 1 在这两种情况下,都应在执行分配后检查NULL ,以确保可以访问此类指针而不会引起未定义的行为

It would seem you are on the right track with the design, it is just the implementation that's questionable. 看来您在设计上步入正轨,只是实现存在问题。 As mentioned in comments, you should never hide pointers behind typedefs and opaque pointers is no exception to this. 正如评论中提到的那样,永远不要将指针隐藏在typedef后面,并且不透明的指针也不例外。 If the caller believes that these are allocated variables, they may decide to do stupid things like this: 如果调用者认为这些是分配的变量,则他们可能会决定执行以下愚蠢的操作:

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!!!

So stop hiding the pointers. 因此,停止隐藏指针。 With some slight modifications you should get the code to work as expected: 经过一些细微的修改,您应该可以使代码按预期工作:

external.h external.h

typedef struct external_t external_t;

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

external.c external.c

#include "external.h"

external_t* external_create (/* parameters here */)
{
  external_t* ext = malloc(sizeof *ext);
  /* initialize stuff here */
  return ext;
}

internal.h internal.h

#include "external.h"

typedef struct internal_t internal_t;

internal_t* internal_create (/* parameters here */);

internal.c 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;
}

The caller will have to use pointers too. 调用者也将不得不使用指针。


Also, there is no need to cast the result of malloc. 同样,也不需要强制转换malloc的结果。 Beat the dead horse here: 在这里击败死马:
Do I cast the result of malloc? 我要转换malloc的结果吗? .

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM