C 是否具有通用的“指向指针的指针"?类型? [英] Does C have a generic "pointer to a pointer" type?

查看:70
本文介绍了C 是否具有通用的“指向指针的指针"?类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,如果我想写一个使指针归零的free",我可以这样写:

For example, if I wanted to write a "free" that nulled the pointer, I could write something like:

void myfree(void **data) {
    free(*data);
    *data = NULL;
}

但是,当我尝试编写此代码时,我收到编译器警告(来自 gcc 4.6.2)说:警告:从不兼容的指针类型 [默认启用] 传递参数 1 的 'myfree' ...注意:预期为 'void **' 但参数类型为 'char **'(在本例中,我正在释放一个字符数组).

however, when I try to write this, I get a compiler warning (from gcc 4.6.2) saying: warning: passing argument 1 of ‘myfree’ from incompatible pointer type [enabled by default] ... note: expected ‘void **’ but argument is of type ‘char **‘ (in this case, I am freeing a char array).

void* 似乎是一种特殊情况,可以避免这种警告,因为 callocfree 等不会触发此类警告警告,但 void** 不是(鉴于上述情况).唯一的解决方案是明确的演员阵容,还是我误解了什么?

It seems that void* is special cased to avoid this kind of warning, since calloc, free etc. don't trigger such warnings, but void** is not (given the above). Is the only solution an explicit cast, or have I misunderstood something?

[我正在重新审视最近一个项目中的一些痛点,想知道如何才能更好地处理它们,所以我正在研究极端情况,因此今天的 C 问题.]

[I am revisiting some pain points in a recent project, wondering how they could have been handled better, and so am poking at corner cases, hence the C questions today.]

update 考虑到 void* 是特殊情况,我可以使用 void* 解决这个问题,并在 myfree,但这将是一个有点不负责任的解决方案,因为每个人和他们的狗都会传递一个指向看起来像 free 的东西的指针,所以我需要某种基于间接程度"的编译器警告因为这是一个实用的解决方案.因此产生了通用指向指针的指针"的想法.

update given that void* is special cased, I could hack around this using void* and casts inside myfree, but that would be a somewhat irresponsible solution because everyone and their dog are going to pass a pointer to something that looks like free, so I need some kind of compiler warning based on "degree of indirection" for this to be a practical solution. hence the idea of a generic "pointer to a pointer".

推荐答案

从技术上讲,该标准允许不同的对象指针类型具有不同的表示形式(甚至不同的大小),尽管 char*void* 必须具有相同的表示.但以下是UB:

Technically, the standard allows different object pointer types to have different representations (even different sizes), although char* and void* are required have the same representation. But the following is UB:

int *ip = 0;
free(*(void**)(&ip));

仅仅是因为 ip 的内存不需要与 void* 的内存大小相同,即使它是空指针的位模式int* 类型不需要与 void* 类型的空指针的位模式相同.如果它们不同,那么当您将 int* 转换为 void* 或返回时,编译器当然必须插入代码以在它们之间进行转换.

simply because the memory for ip need not be the same size as the memory for a void*, and even if it is the bit pattern for a null pointer of type int* need not be the same as the bit pattern for a null pointer of type void*. If they're different, then of course the compiler has to insert code to convert between them whenever you convert an int* to void* or back.

实际上,实现不会对您这样做(例如 Posix 禁止这样做).

In practice, implementations don't do that to you (and for example Posix forbids it).

但更重要的是,严格的别名规则不允许您使用 void* 类型的左值访问 char* 对象.所以在实践中,对指针表示的关注不会破坏你的代码,但优化器实际上可能会.基本上,如果函数调用 myfree((void**)(&p)) 被内联,那么编译器可能会看到:

More importantly though, the strict aliasing rules don't allow you to access a char* object using an lvalue of type void*. So in practice, concerns about pointer representation will not break your code, but the optimizer actually might. Basically, if the function call myfree((void**)(&p)) gets inlined, then the compiler might see:

char *p = <something>;
void **data = (void**)(&p);
free(*data);
*data = NULL;
// code that reads p

优化器可以注意到 *data = NULL 正在设置一个 void* 类型的对象,而读取 p 的代码"正在读取一个类型为 void* 的对象输入 char*,禁止与那里的另一个 void* 对象别名.所以允许重新排序指令,完全消除 *data = NULL; ,或者可能其他我没有想到的东西会毁了你的一天,但是如果你没有的话,这会加速代码没有违反规则.

The optimizer is allowed to note that *data = NULL is setting an object of type void*, whereas the "code that reads p" is reading an object of type char*, which is forbidden from being aliased with that other, void* object over there. So it is allowed to reorder the instructions, eliminate *data = NULL; entirely, or possibly other things I haven't thought of that will ruin your day, but that would speed the code up if you hadn't broken the rules.

这篇关于C 是否具有通用的“指向指针的指针"?类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆