繁体   English   中英

为什么指针类型转换为浮动不起作用?

[英]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; :类型along int ,这使得的类型&along int *
&a前面的类型转换是空操作。

p的类型是char *这使得*p的类型是char char值存储在 1 个字节上。 在您的程序中为acd使用大于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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM