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

时间:2018-11-08 05:35:48

标签: c

大家好,我正在学习C语言,我正在尝试使用单个char指针打印不同数据类型的值。我几乎可以打印所有数据类型,但打印浮点数有问题。谁能解释为什么这是一个问题?以及如何使用单个指针打印确切的浮点值。很抱歉这个菜鸟问题,如果事实是这样的话。我了解对齐问题。但是确实需要一个解决方案。

更新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

4 个答案:

答案 0 :(得分:2)

这种工作是偶然的。 p是一个char指针;因此*p始终是一个字符。

  • 您将地址a转换为long int *。它已经是long int *了,因为您使用了long int的地址-因此这实际上没有任何作用。然后,将其填充到p的{​​{1}}中。在char *变量中不能保留long int *;现在是char *。现在,您和我们大多数人一样,显然是在使用little-endian体系结构的机器上,因此最小字节在前:您的char *表示为long int a,而{{1} }读取第一个字节。然后,C的另一个特质开始起作用:所有小于[10, 0, 0, 0]的整数参数都以*p的形式传递;因此将字节int转换为int并压入堆栈(或在较新架构的ABI中通过整数寄存器处理),然后10使用{ {1}}格式,期望为int

  • 对于printf%d不会读取 first 字节,而是读取 only 字节;其余的都一样。其余整数类型也一样,您足够友善,永远不要超过 255 127(谢谢Antti Haapala!)(否则您会看到意外的结果)。

  • 但是,int是另外一个故事。浮点数在内存中的表示方式与整数不同。当char ch读取第一个字节时,它会得到与*p完全无关的内容-有点像试图通过万花筒来猜测一幅画。第一个字节被扩展为int并传递给函数。在较旧的体系结构中,它将像浮点数一样被读取,但是在current ABIs中,多达四个(MS)或六个(UNIX)整数和浮点参数通过寄存器传递,它甚至不查看(因为它通过整数寄存器传递,但是float b将查看浮点寄存器)。请记住,这主要是因为您存储指针的方式最终使指针成为*p

  • 16.89中,您执行了非常不同的操作:将指针放在重要的地方。因此,%f的值会变成char *一点;然后您取消引用它,并正确获得decimal(b);然后将其转换为p,最后得到float *(可以用16.89打印,所以一切都很好)。

tl; dr:C变量的类型固定不变。您所做的任何类型转换只在不存储它们时才重要-将它们放入变量后,类型即为变量的类型。

答案 1 :(得分:0)

在此示例程序中执行的类型强制转换没有任何意义。

F.e。 p = (long int*)&a;a的类型为long int,这使得&a的类型为long int *
&a前面的类型是空操作。

p的类型为char *,这使得*p的类型为charchar值存储在1个字节上。在程序中为256ac使用大于d的值,您会发现它为它们打印了错误的值。

您传递给printf()的值必须与您使用的格式说明符匹配,否则您将得到意外的结果。传递整数(*p并使用%f对其进行格式化不会神奇地进行任何类型转换,而只是强制printf()以错误的方式解释*p的位序列并产生意外结果,因为它是undefined behaviour

答案 2 :(得分:0)

您在这里进行的类型转换

p = (float*)&b;

是隐式强制转换,不是必需的。 &b已经是float*类型,不需要强制转换。

您实际上需要在printf语句中进行强制转换。像这样。

printf("Value of b(float): %f\n", *(float*)p);

在所有其他printf语句中也需要类似的强制转换。

如果您要打印int,请使用int指针,而不要使用char指针,这是没有什么用的。

答案 3 :(得分:0)

如果printf期间的类型转换正确,它应该已经工作了

printf("Value of b(float): %f\n", *(float *)p);

float类型与其他任何整数数据类型的表示方式基本不同,它们基本上遵循floating point standard

现在您的代码中的printf期望%f的字符类型为*p,这里已经引发了未定义的行为