我有一个指向内存地址的void指针。然后,我知道了
int指针= void指针float指针= void指针然后,取消对他们的尊重,得到他们的价值。
{
int x = 25;
void *p = &x;
int *pi = p;
float *pf = p;
double *pd = p;
printf("x: n%d\n", x);
printf("*p: %d\n", *(int *)p);
printf("*pi: %d\n", *pi);
printf("*pf: %f\n", *pf);
printf("*pd: %f\n", *pd);
return 0;
}反引用pi(int指针)的输出为25。然而,反引用pf(float指针)的输出为0.000。另外,取消pd(double指针)输出的负数会不断变化吗?
为什么这与endianness有关(我的CPU是小endian)?
发布于 2015-12-21 16:13:28
按照C标准,您可以将任何指针转换为void *并将其转换回来,这将具有相同的效果。
引用未定义行为,第6.3.2.3节
..。指向任何对象类型的指针可以转换为指向
void的指针,然后再转换回来;结果应该与原始指针相比较。
这就是为什么当您将空指针转换为int *时,取消引用并打印结果时,它会正确地打印。
但是,标准并不保证您可以取消引用该指针,使其具有不同的数据类型。它实质上是在援引未定义的行为。
因此,取消引用pf或pd以获得float或double是未定义行为,因为您试图以float或double的形式读取分配给int的内存。有一个明显的案件,米斯马克,这导致了UB。
为了详细说明,int和float (和double)有不同的内部表示形式,因此尝试将指针转换为另一种类型,然后尝试取消引用以获得其他类型的值是行不通的。
相关,C11,第6.5.3.3节
..。如果操作数有“指向类型”的“指针”类型,则结果具有“类型”类型。如果已将无效值分配给指针,则不定义一元
*运算符的行为。
对于无效值部分,(强调值)
由一元*运算符取消引用指针的无效值包括空指针、针对指向的对象类型不适当地对齐的地址以及对象生存期结束后的地址。
发布于 2015-12-21 16:38:27
除了前面的答案之外,我认为,由于浮点数的表示方式,无法实现您所期望的结果。
整数通常是以二补方式存储的,基本上意味着数字是作为一个整体存储的。另一方面,浮标使用不同的方式存储,使用符号、基和指数在这里读。
因此,转换的主要思想是不可能的,因为您尝试将一个数字表示为原始位(对于正数),并将其视为不同的编码,这将导致意外的结果,即使转换是合法的。
发布于 2015-12-21 16:43:14
所以..。可能这是怎么回事。
但是,取消引用pf(浮点数指针)的输出为0.000。
不是0。它真的很小。
你有4字节整数。你的整数在记忆中是这样的..。
5 0 0 0
00000101 00000000 00000000 00000000它被解释为浮动看起来像..。
sign exponent fraction
0 00001010 0000000 00000000 00000000
+ 2**-117 * 1.0所以,你在输出一个浮子,但它非常小。它是2^-117,与0几乎没有区别。
如果您尝试用printf("*pf: %e\n", *pf);打印浮点,那么它应该会给您一些有意义但很小的东西。7.006492e-45
另外,取消pd(双指针)输出的负分数会不断变化吗?
双字节是8字节,但你只定义了4字节.负分数变化是观察未初始化内存的结果。未初始化内存的值是任意的,看到它随每次运行而变化是正常的。
https://stackoverflow.com/questions/34399869
复制相似问题