在一行中投射和引用

时间:2018-06-13 06:57:03

标签: c

检查代码:

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。
请告知问题的更好标题。

4 个答案:

答案 0 :(得分:4)

施放&cb_p是不明智的。 float**void**不兼容指针类型。假设"所有指针都相同"不需要保持一般。

然而,你可以做一些几乎看起来像演员的事,但不是一个。您可以使用复合文字。该表达式创建一个左值,与强制转换生成的常规值不同。你可以拿一个左值的地址:

mem_set( &(void*){cb_p}, &mem_pos );  

(void*){cb_p}生成一个未命名的void指针(这是复合文字表达式),它是从cb_p初始化的。由于它是左值,因此可以合法地获取地址。这将避免你想要的临时名称。

确保您的编译器支持或更高版本。

答案 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 *&cbfloat **。演员表会转换为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 );