C 方法将double传递给void*参数

C 方法将double传递给void*参数,c,strict-aliasing,C,Strict Aliasing,我的问题是需要通过void*函数参数正确传递double变量。我这样问是因为在我的机器上,sizeof(void*)是4,sizeof(double)是8,将一个强制转换到另一个似乎会导致问题,但我的编译器(发出所有警告的叮当声)没有显示问题,代码似乎工作正常 请注意,我已经看到,并且。他们在标题中有相似的成分词,但没有回答这个特定的问题 以下情况是否会导致严格的别名冲突错误?或未定义的行为 // some calling function double a = 0.000234423; fun

我的问题是需要通过
void*
函数参数正确传递
double
变量。我这样问是因为在我的机器上,
sizeof(void*)
4
sizeof(double)
8
,将一个强制转换到另一个似乎会导致问题,但我的编译器(发出所有警告的叮当声)没有显示问题,代码似乎工作正常

请注意,我已经看到,并且。他们在标题中有相似的成分词,但没有回答这个特定的问题

以下情况是否会导致严格的别名冲突错误?或未定义的行为

// some calling function
double a = 0.000234423;
func1(&a);

...

void func1(void *var)
{
    double a = *(double *)(var);
}

通常的解决方案确实是传递双变量的地址,因此a
double*
。它的大小不大于一个
void*

通常的解决方案确实是传递双变量的地址,因此a
double*
。它的大小不大于一个
void*

指针的大小与它指向的元素的大小无关

4字节指针可以毫无问题地指向8字节或32字节或任意大小的元素

我这样问是因为在我的机器上,sizeof(void*)是4,sizeof(double)是8,将一个值转换为另一个值似乎会导致问题

如果你把一个4字节的指针转换成一个8字节的双精度,这将是一个大问题。然而,这并不是你的代码在做什么

这就是代码所做的:

double a = * (double *)(var);
           | \--------------/
           |  This casts a void pointer to a double pointer
           |
           --> This dereferences the double pointer, i.e. reads the value of the pointed
               to element (aka the pointed to double)
由于void指针是从double的地址创建的,因此将其转换回double指针是完全合法的,读取pointed-to元素的值也是完全合法的。换句话说,在函数调用过程中,您将双指针隐式转换为无效指针,并且在函数内部无效指针将转换回双指针。完全合法的C代码

通过额外的步骤,您的代码相当于:

void func1(void *var)
{
    double *pd = (double *)var;
    double a = *pd;
}

这使它更加清晰。

指针的大小与其指向的元素的大小无关

4字节指针可以毫无问题地指向8字节或32字节或任意大小的元素

我这样问是因为在我的机器上,sizeof(void*)是4,sizeof(double)是8,将一个值转换为另一个值似乎会导致问题

如果你把一个4字节的指针转换成一个8字节的双精度,这将是一个大问题。然而,这并不是你的代码在做什么

这就是代码所做的:

double a = * (double *)(var);
           | \--------------/
           |  This casts a void pointer to a double pointer
           |
           --> This dereferences the double pointer, i.e. reads the value of the pointed
               to element (aka the pointed to double)
由于void指针是从double的地址创建的,因此将其转换回double指针是完全合法的,读取pointed-to元素的值也是完全合法的。换句话说,在函数调用过程中,您将双指针隐式转换为无效指针,并且在函数内部无效指针将转换回双指针。完全合法的C代码

通过额外的步骤,您的代码相当于:

void func1(void *var)
{
    double *pd = (double *)var;
    double a = *pd;
}

这就更清楚了。

如果接收类型为
void*
的参数的函数需要接收双精度值,则可以定义结构、函数和宏:

struct doubleWrapper { double d[1]; };
struct doubleWrapper doWrapDouble(double d)
{      
  return (struct doubleWrapper){d};
}
#define wrapDouble(x) (doWrapDouble((x)).d)
然后在需要传递
double
值的呼叫站点使用该函数:

void functionTakingVoid(int mode, void *param)
{
  if (mode==0)
  {
    double myDouble = *(double*)param;
    ...
  }
}

void passDoubleToFunctionTakingVoid(double myValue)
{
  functionTakingVoid(0, wrapDouble(myValue));
}

在C99下,
wrappouble
宏将返回一个指向double的指针,该double的生存期将延长到对封闭完整表达式的求值,包括由此进行的函数调用。

如果接收类型为
void*
的参数的函数需要接收一个double值,则可以定义一个结构、函数、,和宏观:

struct doubleWrapper { double d[1]; };
struct doubleWrapper doWrapDouble(double d)
{      
  return (struct doubleWrapper){d};
}
#define wrapDouble(x) (doWrapDouble((x)).d)
然后在需要传递
double
值的呼叫站点使用该函数:

void functionTakingVoid(int mode, void *param)
{
  if (mode==0)
  {
    double myDouble = *(double*)param;
    ...
  }
}

void passDoubleToFunctionTakingVoid(double myValue)
{
  functionTakingVoid(0, wrapDouble(myValue));
}

在C99下,
wrappouble
宏将返回一个指向double的指针,该double的生存期将延长到对封闭的完整表达式的求值,包括由此进行的函数调用。

您的4字节指针指向一个8字节的对象。问题是什么?您的问题是希望在指针的值中存储一个双精度值,但您的代码表示希望在指针中存储指向双精度值的指针。是哪一个?“只有一个是有意义的,但你仍然应该是具体的。”物理学家:我看不到任何地方它字面上说要存储一个双倍值。问题是如何传递一个双变量,而基本答案归结为“通过引用传递”,因为“通过值传递”不起作用。只要你不进行肮脏的攻击,也就是将值转换为指针,然后让回调函数从指针转换回整数,就可以了。显然,这是各种Thrash pthread应用程序中常见的黑客行为(因为它们担心如果通过ref传递,原始值将超出范围)。
sizeof(void*)是4
?如果该
void*
以指向124513字节
char
数组的
char*
开头,该怎么办?您的4字节指针指向一个8字节的对象。问题是什么?您的问题是希望在指针的值中存储一个双精度值,但您的代码表示希望在指针中存储指向双精度值的指针。是哪一个?“只有一个是有意义的,但你仍然应该是具体的。”物理学家:我看不到任何地方它字面上说要存储一个双倍值。问题是如何传递一个双变量,而基本答案归结为“通过引用传递”,因为“通过值传递”不起作用。只要你不进行肮脏的攻击,也就是将值转换为指针,然后让回调函数从指针转换回整数,就可以了。显然,这是各种thrashy pthread应用程序中常见的黑客行为(因为他们担心原始值会丢失)