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*
通常的解决方案确实是传递双变量的地址,因此adouble*
。它的大小不大于一个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应用程序中常见的黑客行为(因为他们担心原始值会丢失)