检查代码:
void mem_set( void** mem_input, void** mem_current )
{
*mem_input = *mem_current;
...
}
main()
{
...
void* mem_pos = ...;
float* cb_p = ...;
void* temp = (void*)cb_p;
mem_set( ( &temp, &mem_pos ); // works, but clumsy
}
我想避免在调用mem_set
时创建和填充临时变量(因为我有很多mem_set
次调用)。这个电话可以在一条线上完成吗?
mem_set( ( &( (void*)cb_p ), &mem_pos )
不起作用。
P.S。
请告知问题的更好标题。
答案 0 :(得分:4)
施放&cb_p
是不明智的。 float**
和void**
不兼容指针类型。假设"所有指针都相同"不需要保持一般。
然而,你可以做一些几乎看起来像演员的事,但不是一个。您可以使用复合文字。该表达式创建一个左值,与强制转换生成的常规值不同。你可以拿一个左值的地址:
mem_set( &(void*){cb_p}, &mem_pos );
(void*){cb_p}
生成一个未命名的void指针(这是复合文字表达式),它是从cb_p
初始化的。由于它是左值,因此可以合法地获取地址。这将避免你想要的临时名称。
确保您的编译器支持c99或更高版本。
答案 1 :(得分:2)
在使用临时工时要小心!
这不会改变cb_p
的价值:
void* temp = (void*)cb_p;
mem_set( &temp, &mem_pos ); // works, but clumsy
因为temp是一个不同的指针,它最初指向与cb_p
相同的对象。因此mem_set
仅更改temp
的值并保持cb_p
不变。
这也意味着这个(完全符合标准的)解决方案也不会改变cb_p
:
mem_set( &(void*){&cb_p}, &mem_pos );
&(void*){&cb_p}
创建一个临时void *
指针,此处再次使用cb_p
的值进行初始化,只有mem_set
更改临时值。
演示代码:
float f1 = 1., f2 = 2.;
void* mem_pos = &f2;
float* cb_p = &f1;
//void* temp = (void*)cb_p;
mem_set(&(void*){&cb_p}, &mem_pos ); // works, but clumsy
printf("%f\n", *cb_p);
输出
1.000000
如果您想更改cb_p
,则必须传递自己的地址:
mem_set((void**)&cb_p, &mem_pos );
使用此行,上面的演示输出2.000000
。
此处所需的唯一实现依赖功能是指向任何类型的指针应具有相同的对齐和表示。 mem_pos
是从void *
初始化的float *
。因此,它可以合法地返回到float *
并将获得原始值。
cb_p
, float *
为&cb
和float **
。演员表会转换为void **
。接下来,指向的值接收另一个指针值。这里要求void*
和float*
具有相同的表示,标准不保证这一点,但在我所知的所有实现中都是如此:指针不超过内存地址对象的第一个字节(*)。
如果实施允许这一点,则cb_p
已分配了从void *
初始化的float *
的值。这里再次提供了所有指针具有相同的表示,cb_p
当前表示是指向浮动对象的指针的表示:cb_p
指向该对象。
(*)不幸的是,C11的草案n1570在6.2.6.1概述
中说1除非本条款规定,否则所有类型的陈述都没有说明。
并且子条款没有说明指针表示的任何内容
答案 2 :(得分:1)
试试这个:
mem_set ( (void **)&cb_p, &mem_pos);
答案 3 :(得分:1)
实际上,C中的转换语法是。
(type)value
此处您的值为&cb_p
,类型为void**
而不是void*
mem_set ( (void**)&cb_p, &mem_pos );