Thread: Pointers and Casting Pointers

  1. #1
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629

    Pointers and Casting Pointers

    Pointers and Address?
    Hi can anyone tell me whats the difference between this 2 statements?
    Code:
    float num = 100.75 ;
    unsigned int a= *((unsigned int*)&num) ;
    //for this I am getting a value like 3247..and so on
    and this:
    Code:
    float num = 100.75 ; 
    unsigned int a = (unsigned int)num ;
    //I am getting 100
    why am I not getting the same result in a for both the statements?

    Does casting the address to be of int type make it different or something?
    I know that floating point numbers are stored differently in memory..
    the decimal part and the fractional part are calculated separately then it is normalised..

    so when I do that
    and I cast the address to be of type unsigned int..
    does it just take the binary and convert it to a decimal number so it can be stored in the unsigned int variable?

    for the second statement why am I getting a 100 and not a number that looks random, i mean
    the floating point number is stored in the same way so why will it just chop off the fractional part and print the decimal part..
    is it because in the first statement i am actually trying to change how the floating point value is stored in memory?
    thanks
    Please make your answer simple as possible . thanks
    Last edited by Eman; 10-16-2010 at 12:58 PM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > Does casting the address to be of int type make it different or something?
    Yes, it makes it wrong.

    In the first instance, you just take a bunch of bits representing a float, and pretend they represent an unsigned int.

    You can get the same effect by doing
    Code:
    union {
       unsigned int i;
       float f;
    } v;
    Assign the value to v.f, and print v.i


    In the second case, you perform a proper numeric conversion from one type to another, and you get the right answer.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    The former reinterprets the binary representation of the float as that of an unsigned int. The latter converts the float to unsigned int, resulting in truncation.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by laserlight View Post
    The former reinterprets the binary representation of the float as that of an unsigned int. The latter converts the float to unsigned int, resulting in truncation.
    So by specifying the address to be stored in a pointer of a different type..i am in effect creating a new value?

    Is that not a bad thing? In what cases would I need to use this method?
    Last edited by Eman; 10-16-2010 at 01:16 PM.

  5. #5
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by Eman View Post
    So by specifying the address to be stored in a pointer of a different type..i am in effect creating a new value?
    It doesn't actually create anything really. In fact in terms of the generated assembly it doesn't actually itself generate any code. You're simply telling it, hey see this memory address here, pretend it's a pointer to an int. Now, what is the value that my int pointer points to?

    Is that not a bad thing? In what cases would I need to use this method?
    You would do that kind of thing if you were doing bit manipulation. A good case for it would be if you were writing a table-driven implementation of a 32-bit IEEE754 float to 16-bit IEEE754 half-float converter. (Which I just so happen to have already).
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Eman
    So by specifying the address to be stored in a pointer of a different type..i am in effect creating a new value?
    It is not so much "creating a new value" as observing the value of the object (as in region of memory) as if it were an unsigned int.

    Quote Originally Posted by Eman
    In what cases would I need to use this method?
    You might want to reinterpret some object as a bunch of bytes, but that should be quite rare. There are other applications involving void pointers, but again, that should be quite rare. Don't worry about it, and for the most part, don't do it.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by iMalc View Post
    It doesn't actually create anything really. In fact in terms of the generated assembly it doesn't actually itself generate any code. You're simply telling it, hey see this memory address here, pretend it's a pointer to an int. Now, what is the value that my int pointer points to?

    You would do that kind of thing if you were doing bit manipulation. A good case for it would be if you were writing a table-driven implementation of a 32-bit IEEE754 float to 16-bit IEEE754 half-float converter. (Which I just so happen to have already).
    Maybe creating is a bad word to use...
    because the int pointer should point to an int, the binary representation of the floating point number was stored to an integer type format?

    so lets say
    100.75 is 0011
    and i did the cast
    Code:
     unsigned int a = *((unsigned int*)&num
    it will just take 0011 and convert it to 3?
    so 3 now will be in a ... the numbers are just an example to understand what is happening in memory.

    but if i did a simple
    Code:
    float num = 100.7
    int a = (int)num;
    it doesn't care about the binary representation and just
    truncates the 0.7 part and stores 100 in a ..
    sorry about the repetition. I am a slow learner and need to be able to visualise it.
    Can you make your explanation simple? THanks

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Eman
    because the int pointer should point to an int, the binary representation of the floating point number was stored to an integer type format?
    The binary representation of the floating point number was treated as if it was the binary representation of an integer.

    Quote Originally Posted by Eman
    it will just take 0011 and convert it to 3?
    Yes, something like that.

    Quote Originally Posted by Eman
    it doesn't care about the binary representation
    Not quite: the binary representation is needed to determine the value.

    Quote Originally Posted by Eman
    truncates the 0.7 part and stores 100 in a
    Yes.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    The thing is that whatever is stored in memory has no type. It's just a bunch of 1s and 0s.
    In order to read and write something, the compiler stores those bits in a predetermined way. And then reads them back in the same way. But the compiler really have no idea what is actually stored in a given memory location. It relies on the type of your variable to know how to interpret the data stored there.
    Now, floating points and integers are not stored the same way. So when you cast the pointer, you are essentially just telling the compiler: hey, there's an int stored there, so read it and store it in this variable. But a floating point is stored completely differently.
    As an example, say, that we have 10.5. Let's say that in memory, it will look like: 1010 0101. The compiler would then read the first 4 bits and interpret this as the integer and the last 4 bits and interpret them as the decimal. But what happens if we tell the compiler it's an integer? The compiler reads all bits and interprets them as one big number and we get 165.

    The second statement is different because you are telling the compiler: we have a float, and I want to convert it to an int. Thus, the compiler does the conversion for you and you get a real integer.

    Hope this helps your understanding a little better.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by Elysia View Post
    The thing is that whatever is stored in memory has no type. It's just a bunch of 1s and 0s.
    In order to read and write something, the compiler stores those bits in a predetermined way. And then reads them back in the same way. But the compiler really have no idea what is actually stored in a given memory location. It relies on the type of your variable to know how to interpret the data stored there.
    Now, floating points and integers are not stored the same way. So when you cast the pointer, you are essentially just telling the compiler: hey, there's an int stored there, so read it and store it in this variable. But a floating point is stored completely differently.
    As an example, say, that we have 10.5. Let's say that in memory, it will look like: 1010 0101. The compiler would then read the first 4 bits and interpret this as the integer and the last 4 bits and interpret them as the decimal. But what happens if we tell the compiler it's an integer? The compiler reads all bits and interprets them as one big number and we get 165.

    The second statement is different because you are telling the compiler: we have a float, and I want to convert it to an int. Thus, the compiler does the conversion for you and you get a real integer.

    Hope this helps your understanding a little better.
    I love your explanation thanks.
    but one more question..
    So whenever i am using a cast on an address to be stored in a different type (or any type) the binary is always interpreted to be stored as the typecast specified.
    But if it is not a pointer cast (like casting a float to an int (float)num),
    because it isn't casting (changing, inverting) the address it doesn't interpret the binary representation.

    I am just trying to understand why in one scenario it interprets the binary representation and in other it merely truncates the values.

    Is it because of casting the address, merely using a pointer?

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Ah, but you must separate casts and dereferencing.
    The pointer cast is done much the same as float -> int or vice versa. The float* is converted to a int* by the compiler. Since they're the same size and all (doesn't always hold true for all platforms), the conversion is trivial. That is, nothing really happens. The compiler just stores the old value in the new variable.
    But when you dereference a pointer, then the magic happens. No conversion is done here.

    So, to summarize:
    Code:
    float x = 10.0f;
    int y = (int)x;
    int z = *(int*)&x;
    1) Compiler converts the float to an integer.
    2) Compiler stores integer in y.

    Second line:
    1) Compiler converts the address of x from float* to int*. Conversion is trivial; the old value is just copied.
    2) The compiler goes to the address pointed to by the pointer and reads the data.
    3) The compiler stores the data in the variable.

    So what would happen if we did
    Code:
    float z = *(float*)&x;
    ?

    1) Compiler converts the address of x from float* to float*. Conversion is trivial; the old value is just copied.
    2) The compiler goes to the address pointed to by the pointer and reads the data.
    3) The compiler stores the data in the variable.

    Essentially, only step 1 is altered. Do you see? The compiler simply relies on the type of pointer to know how to interpret the data. But since we change the pointer type, we also change how the compiler interprets the data. The data itself is never changed or converted, only the pointer type.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    because it isn't casting (changing, inverting) the address it doesn't interpret the binary representation.
    Typecasting always looks at the binary representation. Binary is the basic building block of everything the computer can store or do.

    What is happening when you cast a float variable as an unsigned integer: You are taking the float's value and throwing away the fractional part. What is happening when you cast the float as an unsigned integer pointer and dereference that pointer: first the address of the float is taken and then given to a temporary integer pointer. That integer pointer is dereferenced, so you get the first half or so of the bits of the floating point number interpreted as an integer.

    The bits of a real number may make sense as a whole number integer, but you are ignoring some of the bits so you have less information (wrong information).

    If you merely did:

    int num = whatever;
    float mun = whatever;
    num = mun;

    The compiler would ........... Part of the reason casting is dangerous is because people think they're getting something they want out of it. It's almost always used superficially.
    Last edited by whiteflags; 10-16-2010 at 05:18 PM.

  13. #13
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    so the difference between the changing the address and dereferencing it

    Code:
    float x = 10.0f;
    int z = *(int*)&x;
    No conversion takes place. The compiler treats the dereferenced value as an int and stores it into z.

    and simply using a typecast
    Code:
    int y = (int)x;
    while in this code the compiler does not treat the value of x as an int.
    it just converts it to be an int and stores it in y, but the value of x would would remain intact.

    For the value of x to remain intact I would imagine it uses some temporary memory location to store data while it is conversion.

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You got it down pretty good.
    But I'll just point out one thing:
    There is a conversion taking place. That is, float* -> int* (address to address).
    In the later, it's float -> int (floating point value to integer).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #15
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by Elysia View Post
    You got it down pretty good.
    But I'll just point out one thing:
    There is a conversion taking place. That is, float* -> int* (address to address).
    In the later, it's float -> int (floating point value to integer).
    yep i get ya
    thank you dude..
    thanks all
    I have been struggling with this concept for a few days..now I understand what is happening.
    Thanks, I appreciate it.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 8
    Last Post: 05-21-2009, 05:47 PM
  2. Casting and Pointers
    By kpreston in forum C Programming
    Replies: 10
    Last Post: 08-28-2008, 08:23 PM
  3. simple question about pointers and casting
    By steve1_rm in forum C++ Programming
    Replies: 3
    Last Post: 03-28-2008, 02:25 PM
  4. Replies: 8
    Last Post: 01-23-2008, 04:22 AM
  5. casting int and float pointers
    By mhaak in forum C Programming
    Replies: 3
    Last Post: 05-13-2005, 05:19 PM