双指针转换,使用`const void**ptr`参数传递给函数

KAc*_*ion 5 c gcc pointers

海湾合作委员会给了我以下警告:

note: expected 'const void **' but argument is of type 'const struct auth **
Run Code Online (Sandbox Code Playgroud)

有没有可能导致问题的情况?

更大的片段是

struct auth *current;
gl_list_iterator_next(&it, &current, NULL);
Run Code Online (Sandbox Code Playgroud)

函数只存储在current一些void *指针中.

Fre*_*Foo 7

该错误信息是足够清晰:你传递一个struct auth **,其中一个void **被接受.这些类型之间没有隐式转换,因为它void*可能与其他指针类型的大小和对齐方式不同.

解决方案是使用中间体void*:

void *current_void;
struct auth *current;

gl_list_iterator_next(&it, &current_void, NULL);
current = current_void;
Run Code Online (Sandbox Code Playgroud)

编辑:为了解决下面的评论,这里有一个为什么这是必要的例子.假设你在一个平台上sizeof(struct auth*) == sizeof(short) == 2,同时sizeof(void*) == sizeof(long) == 4; 这是C标准所允许的,实际上存在具有不同指针大小的平台.那么OP的代码将类似于做

short current;
long *p = (long *)(&current);  // cast added, similar to casting to void**

// now call a function that does writes to *p, as in
*p = 0xDEADBEEF;               // undefined behavior!
Run Code Online (Sandbox Code Playgroud)

但是,这个程序也可以通过引入一个中间体来工作long(虽然结果可能只有在long值足够小以存储在a中时才有意义short).

  • @Kache:区别在于中间的`void*`用作一个位置,其中`void*`类型的值可以通过间接"void**"来存储.假设某个平台上的`struct auth*`小于`void*`(可能会发生),那么OP的代码+一个强制转换可能会超过`&current`的结尾.这就好像你将`short*'强制转换为`long*`然后通过间接存储`long`. (2认同)