[英]Why does pointer typecasting to float doesn't work?
大家好,我正在学习 C,我正在尝试使用单个字符指针打印不同数据类型的值。 我几乎可以打印所有数据类型,但在打印浮点数时遇到问题。 谁能解释为什么这是一个问题?! 以及如何使用单个指针打印精确的浮点值。 对不起,菜鸟问题,如果结果是一个。 我理解对齐问题。 但真的需要一个解决方案。
更新 1--> 为愚蠢的类型转换感到抱歉。 现在考虑更新代码。
更新 2 --> 谢谢大家的回答。 就像我说的,我正在学习 C,抱歉语法错误。 我不是来自 CS 背景。但再次非常感谢你。
#include <stdio.h>
int main()
{
long int a = 10;
char ch = 'a';
float b = 16.89;
unsigned int c = 20;
short int d = 30;
char *p;
p = &a;
printf("Value of a: %d\n", *p);
p = &ch;
printf("Value of ch: %c\n", *p);
p = &b;
printf("Value of b(float): %f\n", *p);
printf("Value of b(decimal): %d\n", (int) *((float*)p));
p = &c;
printf("Value of c: %u\n", *p);
p = &d;
printf("Value of d: %i\n", *p);
return 0;
}
The output of the above program is :-
Value of a: 10
Value of ch: a
Value of b(float): 0.000000
Value of b(decimal): 16
Value of c: 20
Value of d: 30
这种工作是偶然的。 p
是一个字符指针; 所以*p
总是一个字符。
你把地址a
,将其转换成一个long int *
。 它已经是一个long int *
,因为你获取了一个long int
的地址 - 所以这并没有真正做任何事情。 然后你把它塞进p
,这是一个char *
。 它不能在char *
变量中保持long int *
; 它现在是一个char *
。 现在,您显然在使用小端架构的机器上,就像我们大多数人一样,所以最小字节在前:您的long int a
表示为[10, 0, 0, 0]
,并且*p
读取第一个字节。 然后 C 的另一个特性开始发挥作用:所有小于int
整数参数都作为int
传递; 因此字节10
被转换为int
并推送到堆栈(或通过较新架构的 ABI 中的整数寄存器传递),然后由printf
使用%d
格式正确读取,期望int
。
对于char ch
, *p
不读取第一个字节,它读取唯一的字节; 其余的都是一样的。 其余的整数类型也是如此,您永远不会超过
255
127 [谢谢,Antti Haapala!](否则您会看到意想不到的结果)。
但是, float b
是另一回事。 浮点数在内存中的表示方式与整数非常不同; 当*p
读取第一个字节时,它会得到一些与16.89
完全无关的东西 - 有点像在通过万花筒看时试图猜测一幅画。 第一个字节被扩展为 int 并传递给函数。 在较旧的体系结构中,它会像浮点一样被读取,但在当前的 ABI 中,多达四个 (MS) 或六个 (UNIX) 整数和浮点参数通过寄存器传递,它甚至不会被查看(因为它通过一个整数寄存器传递,但%f
将查看一个浮点寄存器)。 请记住,这主要是因为您的指针以char *
结尾,因为您存储它的方式。
在decimal(b)
,您做了一些非常不同的事情:您将指针投射到重要的地方。 所以在这里, p
的值变成了一个float *
位; 然后你取消引用它,并正确地得到16.89
; 然后将其转换为int
,最终得到16
(您用%d
打印,所以一切都很好)。
tl;dr:C 变量的类型是一成不变的。 您所做的任何强制转换仅在您不存储它们时才有意义 - 一旦将它们放入变量中,类型就是变量的类型。
您在此示例程序中执行的类型转换没有任何意义。
Fe p = (long int*)&a;
:类型a
是long int
,这使得的类型&a
为long int *
。
&a
前面的类型转换是空操作。
p
的类型是char *
这使得*p
的类型是char
。 char
值存储在 1 个字节上。 在您的程序中为a
、 c
和d
使用大于256
值,您会发现它会为它们打印出不正确的值。
您传递给printf()
的值必须与您使用的格式说明符匹配,否则您会得到意想不到的结果。 传递一个整数 ( *p
) 并使用%f
对其进行格式化并不会神奇地进行任何类型转换,它只是强制printf()
以不正确的方式解释*p
的位序列并产生意外结果,因为它是未定义的行为。
你在这里做的类型转换
p = (float*)&b;
是隐式转换,不是必需的。 &b
已经是float*
类型并且不需要强制转换。
您实际上需要在printf
语句中进行printf
。 像这样..
printf("Value of b(float): %f\n", *(float*)p);
您也需要在所有其他printf
语句中进行类似的转换。
你在这里所做的没有多大用处,如果你想打印一个int
使用一个int
指针,而不是一个char
指针。
如果printf
期间的类型转换正确,它应该可以工作
printf("Value of b(float): %f\n", *(float *)p);
float
类型与任何其他整数数据类型的表示方式不同,本质上它们基本上遵循浮点标准
现在你的代码中的printf
期望%f
另一方面*p
是 char 类型,这里已经引发了未定义的行为
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.