我正在尝试几个关于做什么和不做类型转换的例子。我无法理解为什么以下代码片段无法输出正确的结果。
/* int to float */
#include<stdio.h>
int main(){
int i = 37;
float f = *(float*)&i;
printf("\n %f \n",f);
return 0;
}
这会打印0.000000
/* float to short */
#include<stdio.h>
int main(){
float f = 7.0;
short s = *(float*)&f;
printf("\n s: %d \n",s);
return 0;
}
这会打印7
/* From double to char */
#include<stdio.h>
int main(){
double d = 3.14;
char ch = *(char*)&d;
printf("\n ch : %c \n",ch);
return 0;
}
这会打印垃圾
/* From short to double */
#include<stdio.h>
int main(){
short s = 45;
double d = *(double*)&s;
printf("\n d : %f \n",d);
return 0;
}
这会打印0.000000
为什么从float
到int
的广告投放会给出正确的结果,而且当明确转换类型时,所有其他转换都会产生错误的结果?
我无法清楚地理解为什么需要对(float*)
进行类型转换而不是float
int i = 10;
float f = (float) i; // gives the correct op as : 10.000
但是,
int i = 10;
float f = *(float*)&i; // gives a 0.0000
上述两种类型演员之间有什么区别?
为什么我们不能使用:
float f = (float**)&i;
float f = *(float*)&i;
答案 0 :(得分:4)
在这个例子中:
char ch = *(char*)&d;
您没有从double
投射到char
。您正在从double*
投射到char*
;也就是说,您正在从双指针转换为char 指针。
C在转换值时会将浮点类型转换为整数类型,但由于您要转换指向这些值的指针,因此不会进行转换。你得到垃圾,因为浮点数的存储方式与固定点数的存储方式截然不同。
答案 1 :(得分:3)
了解系统中浮点数的表示。它不是你期望它的方式。通过(float *)
在您的第一个代码段中进行的转换会读取最重要的前16位。如果您的系统是小端,如果int
类型变量中包含的值小于2^16
,则最重要位中将始终为零。
答案 2 :(得分:1)
如果需要将int转换为float,则转换是直的,因为C的升级规则 所以,写下来就足够了:
int i = 37;
float f = i;
这会得到结果f == 37.0
。
但是,在转换(float *)(&i)
中,结果是一个类型为&#34的对象;指向float&#34 ;.
的指针
在这种情况下,&#34;指向整数&#34;的指针的地址&amp; i与&#34;指向float&#34;的指针相同。 (浮动*)(&amp; i)。但是,最后一个对象指向的对象是float
,其位与对象i
相同,后者是一个整数。
现在,讨论的重点是内存中对象的位表示对于整数和浮点数是非常不同的。
正整数以显式形式表示,正如其二进制数学表达式所规定的那样
但是,浮点数具有其他表示,由尾数和指数组成。
因此,当被解释为整数时,对象的位具有一个含义,但是相同的位(被解释为浮点数)具有另一个非常不同的含义。
答案 3 :(得分:1)
更好的问题是,为什么它会发挥作用。你看,当你这样做时
typedef int T;//replace with whatever
typedef double J;//replace with whatever
T s = 45;
J d = *(J*)(&s);
你基本上是在告诉编译器(获取s的T *地址,重新解释它指向J的内容,然后获取该值)。实际上没有转换值(改变字节)。有时,幸运的是,这是相同的(低值浮点数将具有0的指数,因此整数解释可能是相同的)但通常情况下,这将是垃圾,或者更糟糕的是,如果尺寸不是相同(比如从char转换为double)你可以读取未分配的数据(堆损坏(有时)!)。