简体   繁体   English

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

[英]Why does pointer typecasting to float doesn't work?

Hi everyone I am learning C and i am trying to print values of different data types using a single char pointer.大家好,我正在学习 C,我正在尝试使用单个字符指针打印不同数据类型的值。 I am able to print almost every data type but having problems to print float.我几乎可以打印所有数据类型,但在打印浮点数时遇到问题。 Can anyone explain why this is an issue ?!谁能解释为什么这是一个问题?! And how can i print the exact float value using a single pointer.以及如何使用单个指针打印精确的浮点值。 Sorry for the noob question, if it turns out to be one.对不起,菜鸟问题,如果结果是一个。 I understand the alignment problem.我理解对齐问题。 But really need a solution to this.但真的需要一个解决方案。

UPDATE 1--> Sorry for the stupid typecasting.更新 1--> 为愚蠢的类型转换感到抱歉。 Now consider the update code.现在考虑更新代码。

UPDATE 2 --> Thank you everyone for answering.更新 2 --> 谢谢大家的回答。 Like i said,i am learning C, sorry for the syntax errors.就像我说的,我正在学习 C,抱歉语法错误。 I am not from CS background.But thank you so much again.我不是来自 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

This kind of works by accident.这种工作是偶然的。 p is a char pointer; p是一个字符指针; so *p is always a char.所以*p总是一个字符。

  • You take the address of a , converting it into a long int * .你把地址a ,将其转换成一个long int * It already was a long int * , because you took an address of a long int - so this doesn't really do anything.它已经是一个long int * ,因为你获取了一个long int的地址 - 所以这并没有真正做任何事情。 Then you stuff it into p , which is a char * .然后你把它塞进p ,这是一个char * It cannot remain a long int * while in a char * variable;它不能在char *变量中保持long int * it's now a char * .它现在是一个char * Now, you are apparently on a machine that uses little-endian architecture, like the majority of us, so the least byte comes first: your long int a is represented as [10, 0, 0, 0] , and *p reads the first byte.现在,您显然在使用小端架构的机器上,就像我们大多数人一样,所以最小字节在前:您的long int a表示为[10, 0, 0, 0] ,并且*p读取第一个字节。 Then another idiosyncracy of C comes into play: all integral parameters smaller than int are passed as int ;然后 C 的另一个特性开始发挥作用:所有小于int整数参数都作为int传递; so the byte 10 gets converted into an int and pushed to the stack (or handed through an integer register in newer architectures' ABI), which is then correctly read off by printf using %d format, expecting an int .因此字节10被转换为int并推送到堆栈(或通过较新架构的 ABI 中的整数寄存器传递),然后由printf使用%d格式正确读取,期望int

  • For char ch , *p doesn't read the first byte, it reads the only byte;对于char ch*p不读取第一个字节,它读取唯一的字节; and the rest is all the same.其余的都是一样的。 Ditto for the rest of integral types, where you were kind enough never to go over 255 127 [thanks, Antti Haapala!] (or you'd see an unexpected result).其余的整数类型也是如此,您永远不会超过 255 127 [谢谢,Antti Haapala!](否则您会看到意想不到的结果)。

  • However, float b is a different story.但是, float b是另一回事。 Floats are represented in memory in a very different way than integers;浮点数在内存中的表示方式与整数非常不同; when *p reads the first byte, it gets something quite unrelated to 16.89 - kind of like trying to guess a painting while looking through a kaleidoscope.*p读取第一个字节时,它会得到一些与16.89完全无关的东西 - 有点像在通过万花筒看时试图猜测一幅画。 The first byte gets expanded to int and passed to the function.第一个字节被扩展为 int 并传递给函数。 In an older architecture, it would then get read as if it were float, but in current ABIs , where up to four (MS) or six (UNIX) integral and float parameters get passed through registers, it doesn't even get looked at (since it gets passed through an integral register, but %f will look at a float register).在较旧的体系结构中,它会像浮点一样被读取,但在当前的 ABI 中,多达四个 (MS) 或六个 (UNIX) 整数和浮点参数通过寄存器传递,它甚至不会被查看(因为它通过一个整数寄存器传递,但%f将查看一个浮点寄存器)。 Remember, this is mostly because your pointer ends up as a char * , because of the way you store it.请记住,这主要是因为您的指针以char *结尾,因为您存储它的方式。

  • In decimal(b) , you do something very different: you cast the pointer where it matters .decimal(b) ,您做了一些非常不同的事情:您将指针投射到重要的地方 So here, the value of p gets to be a float * for a bit;所以在这里, p的值变成了一个float *位; then you dereference it, and correctly get 16.89 ;然后你取消引用它,并正确地得到16.89 then you convert that to an int , and end up with 16 (which you print with %d , so all is fine).然后将其转换为int ,最终得到16 (您用%d打印,所以一切都很好)。

tl;dr: Type of C variables is set in stone. tl;dr:C 变量的类型是一成不变的。 Any casts you do only matter while you're not storing them - as soon as you put them in a variable, the type is the variable's type.您所做的任何强制转换仅在您不存储它们时才有意义 - 一旦将它们放入变量中,类型就是变量的类型。

The type casts you do in this sample program do not make any sense.您在此示例程序中执行的类型转换没有任何意义。

Fe p = (long int*)&a; Fe p = (long int*)&a; : the type of a is long int and this makes the type of &a to be long int * . :类型along int ,这使得的类型&along int *
The type cast in front of &a is a no-op. &a前面的类型转换是空操作。

The type of p is char * and this makes the type of *p to be char . p的类型是char *这使得*p的类型是char A char value is stored on 1 byte. char值存储在 1 个字节上。 Use values larger than 256 in your program for a , c and d and you'll discover that it prints incorrect values for them.在您的程序中为acd使用大于256值,您会发现它会为它们打印出不正确的值。

The value you pass to printf() must match the format specifier you use, otherwise you get unexpected results.您传递给printf()的值必须与您使用的格式说明符匹配,否则您会得到意想不到的结果。 Passing an integer ( *p ) and formatting it using %f does not magically do any type conversion, it just forces printf() interpret the sequence of bits of *p in an incorrect way and produce unexpected results because it is undefined behaviour .传递一个整数 ( *p ) 并使用%f对其进行格式化并不会神奇地进行任何类型转换,它只是强制printf()以不正确的方式解释*p的位序列并产生意外结果,因为它是未定义的行为

The typecasts you are doing here你在这里做的类型转换

p = (float*)&b;

is in implicit cast and is not required.是隐式转换,不是必需的。 Already, &b is of type float* and does not need a cast. &b已经是float*类型并且不需要强制转换。

You actually need a cast in the printf statement.您实际上需要在printf语句中进行printf Like this..像这样..

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

You need similar casts in all other printf statements too.您也需要在所有其他printf语句中进行类似的转换。

What you are doing here is of not much use, if you want to print an int use an int pointer, not a char pointer.你在这里所做的没有多大用处,如果你想打印一个int使用一个int指针,而不是一个char指针。

it should have worked had the typecast during printf is correct如果printf期间的类型转换正确,它应该可以工作

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

the float types do not represent in a similar as that of any other integral data types essentially they essentially follow floating point standard float类型与任何其他整数数据类型的表示方式不同,本质上它们基本上遵循浮点标准

now printf in your code expects a %f on the other hand *p is of type char, already an undefined behavior is induced in here现在你的代码中的printf期望%f另一方面*p是 char 类型,这里已经引发了未定义的行为

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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