Casting float to int pointer and back to float?

你说的曾经没有我的故事 提交于 2021-02-08 11:59:26

问题


Can some explain me the behavior of this C program I was trying to understand its behavior...

#include<stdio.h>
float x = 3.33,*y,z;
int *a,b;
int main() {
    a = (int *)&x;
    b = (int)x;
    y = (float *)a;
    z = (float)b;
    printf("\nOriginal Value of X: %f \ncasting via pointer A:%d and back Y: %f \ndirect casting B:%d and back Z:%f\n",x,*a,*y,b,z);
}

Output:

Original Value of X: 3.330000                                                                                                                                                   

casting via pointer A:1079320248 and back Y: 3.330000                                                                                                                           

direct casting B:3 and back Z:3.000000     

OK so why is the value of A is 1079320248 and its not some random value its always the same for X = 3.33 and it changes if X is changed to some different value I was expecting something like A to be 3 but its not.


回答1:


There is no such thing as 'casting via pointer A' happening in your code. You are just forcing the compiler to point a to a float value, where it is assumed to be pointing to an integer.

Using the page pointed out by Reymond Chen in the comment section, we get the binary representation of 3.33 as:

01000000010101010001111010111000

Now, use this page to find its 32-bit signed integer equivalent. You'll get 1079320248, which is the exact non-random number that puzzles you.

If this doesn't make any sense to you, let me make it much clearer. Both a and y are pointing to the same binary value 01000000010101010001111010111000, which represents two different values (3.33 as float and 1079320248 as int) depending on the data type you tell the compiler to use for it.

Update:

Just for academic interest, if you want the printf statement to print 3 for A, replace the third parameter with this:

(int) *((float *)a)




回答2:


TL;DR Casting a pointer to a different non-compatible type and back and then accessing the last one is OK, the problem starts when you try to use the intermediate pointer with non-compatible type.


To elaborate, your code causes undefined behavior because you violate strict aliasing rule.

Quoting C11, chapter §6.5

An object shall have its stored value accessed only by an lvalue expression that has one of the following types:88)

— a type compatible with the effective type of the object,

— a qualified version of a type compatible with the effective type of the object,

— a type that is the signed or unsigned type corresponding to the effective type of the object,

— a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,

— an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or

— a character type.

So in your case, for a definition like

 float x = 3.33,*y,z;
 //....
  a = (int *)&x;
  b = (int)x;
  y = (float *)a;

You are first casting a pointer to float to an integer pointer and then, casting it back to float * and according to the rule mentioned in chapter §6.3.2.3/P7

A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned 68) for the referenced type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer. [...]

So, accessing y is fine, but not a. You will face alignment mismatch, which leads to UB. Don't try to do that. Respect the types.



来源:https://stackoverflow.com/questions/44512402/casting-float-to-int-pointer-and-back-to-float

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!