Thread: casting non-lvalues

  1. #1
    Registered User
    Join Date
    Feb 2002
    Posts
    465

    casting non-lvalues

    I know the handy trick to cast float bits to ints and vice versa using *(int*)(&fNum) and its inverse, but what about when I want to cast non lvalue bits to a float.

    for example, I can't think of a reason I would ever need to do this, but lets pretend I want to make a macro that generates a negative float, and I wrote the macro as follows:

    Code:
    //forgive me for any errors in this, its only an example
    #define MAKE_NEG_FLOAT(exp,mantissa) \
    (0x80000000 | (((exp)&0x000000FF)<<23) | ((mantissa)&0x008FFFFF)
    and then lets say I want to call a function that accepts a float and I want to pass in whatever this function returns.

    Code:
    void func(float num);
    //...
    func( MAKE_NEG_FLOAT(10, 0) );
    The MAKE_NEG_FLOAT macro resolves to an integer, and then the func will cast that to a float rather than converting it to a float with the same bits. My question is this: is there any way, given the setup or a similar setup of code, that would allow me to convert the non-lvalue integer return of a macro directly to a float without casting? Any hackish, crazy way would make me happy, as long as its quick to process and/or could be compiled out with a decent optimized compiler.
    I came up with a cool phrase to put down here, but i forgot it...

  2. #2
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    One option is a union.
    Code:
    #include <stdlib.h>
    #include <stdio.h>
    
    typedef union
    {
       int i;
       float f;
    } int_float;
    
    int main(void)
    {
       int_float num = {0};
    
       printf("%d\n",num.i);
       printf("%f\n",num.f);
    
       num.f = 1;
       printf("%d\n",num.i);
       printf("%f\n",num.f);
    
       return 0;
    }
    Another option is the casting trick you showed above.

  3. #3
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    IMO, such things tend to assume too much about the implementation and should be shunned. Such behavior is undefined.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  4. #4
    Registered User
    Join Date
    Feb 2002
    Posts
    465
    A union would be workable except that it needs to use existing variable types (such as standard 32 bit floats and ints), and the trick I specified does not work for non lvalues (IE, I cant do this: "*(int*)&(0xFFFFFFFF)"), and the macro that I made up resolves to an rvalue.

    IMO, such things tend to assume too much about the implementation and should be shunned. Such behavior is undefined.
    I am not writing a library to distribute on the web or port to other platforms. I need it for a specific purpose for which the implimentation is already known. Also, the only thing I am assuming is the 32 bit IEEE floating point standard, which, if it could not be assumed, would indicate to me that I am working on a platform that does not adhere to even the most basic of standards.

    I am asking for a solution to a problem, not a criticism of its purpose.
    I came up with a cool phrase to put down here, but i forgot it...

  5. #5
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Code:
    func( 0.0f + YOURBROKENSTUFF(10,0) );
    Quzah.
    Hope is the first step on the road to disappointment.

  6. #6
    Registered User
    Join Date
    Feb 2002
    Posts
    465
    wow, lotta testy people today...

    the only thing thats broken about that is your assumptions...

    adding 0.0f to the return value of the macro will only cause the value that it created ( 0x85000000 ) to be cast to a float (2231369728.0f) and then add it to 0.0f, resulting in... well I assume you know at least basic math.

    The whole point of the question is that you cannot modify bits directly in a float, but you can also not cast rvalues to a float using the methods I mentioned previously.

    There is no need to turn this innocent question into a flame war.
    I came up with a cool phrase to put down here, but i forgot it...

  7. #7
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    There are other formats, and the "value of a union member other than the last one stored into" is unspecified*. Casting does much the same, except it turns off error checking.

    But if you want to be testy yourself, at least specify the exact platform and situation. After all, the is a C forum, and your answer is not in the general case.

    *Not undefined as inferred earlier.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  8. #8
    Registered User
    Join Date
    Feb 2002
    Posts
    465
    I believe I did specify the standard as the IEEE Standard (754), but the point of the question has nothing to do with which floating point standard I am using. The question is essentially this: "how do i put rvalue bits inside of a variable for which bit modification is not allowed by C without creating a temporary variable?"

    I use a float simply because it is the most common and easy to understand form of my question.
    Last edited by ...; 08-23-2005 at 09:49 PM.
    I came up with a cool phrase to put down here, but i forgot it...

  9. #9
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by ...
    wow, lotta testy people today...

    the only thing thats broken about that is your assumptions...

    adding 0.0f to the return value of the macro will only cause the value that it created ( 0x85000000 ) to be cast to a float (2231369728.0f) and then add it to 0.0f, resulting in... well I assume you know at least basic math.

    The whole point of the question is that you cannot modify bits directly in a float, but you can also not cast rvalues to a float using the methods I mentioned previously.

    There is no need to turn this innocent question into a flame war.
    Ok, let's start this off right then:

    1) You post some vague ........, like so:
    but what about when I want to cast non lvalue bits to a float.
    What exactly is a "non lvalue bits"? You want to make the right side a float? Or what exactly? Ok, so ........ing add 0.0 to it, and now it's a float.

    2) You then say:
    pretend I want to make a macro that generates a negative float
    What the hell is a "negative float"? A negative floating point number? Well, that's tough too. How about subtracting whatver it is from 0.0f?

    3) Then you say:
    and then lets say I want to call a function that accepts a float and I want to pass in whatever this function returns.
    Man, where to start with this? First off, this doesn't even parse as an English sentence. It's wrong. Well, ok, treat it as C. Well that doesn't work either, because MACROS do not return anything! They're not functions! They can evaluate to something, but they don't "return" anything.

    4) Then you go on to say:
    The MAKE_NEG_FLOAT macro resolves to an integer, and then the func will cast that to a float rather than converting it to a float with the same bits. My question is this: is there any way, given the setup or a similar setup of code, that would allow me to convert the non-lvalue integer return of a macro directly to a float without casting?
    Which I suppose means: "I have some floating point number, and I want to do bit shifting on it, and convert it back to a float." I guess. Is that what you're trying to do? Well you can't, because it's not defined by the standard, which means: ANYTHING YOU DO WILL DIFFER AT WILL! Seriously. If it's not defined, you have no control over what happens. It's prefectly fine for it to change each run time. It probably won't, but you can't assume that. Because it's not defined.

    The bytes of a floating point number aren't stored as they are as an integer. That's why you can't shift them. That's why you can't mask them off. That's why anything you do to them isn't defined.

    Oh, but you don't want to hear that. That's too bad. See, other people read this forum too. So forgive me if I point out things that people want to do that are wrong according to the standard. No, wait a minute, I don't give a ........ what you think. If you don't want to hear it's wrong, don't try to do something that's wrong. Or rather, don't ask people how to do something that's wrong, if you don't want them to tell you it's wrong.

    Oh, wait, it gets better...

    5) You also spit out this gem:
    adding 0.0f to the return value of the macro will only cause the value that it created ( 0x85000000 ) to be cast to a float (2231369728.0f) and then add it to 0.0f, resulting in... well I assume you know at least basic math.
    Well now, had you actually said you just wanted to mung up the the bits and then take these munged up bits, turn them back into a floating point number, in the first place we'd have been all clear wouldn't we?

    In short: No. Why would there be? Why would there be a way to take any random integer value and assume it's not really an integer, but a floating point number? Why on earth would the C language let you do this without a cast. Because that is what you want:
    is there any way, given the setup or a similar setup of code, that would allow me to convert the non-lvalue integer return of a macro directly to a float without casting?
    What? How does this even make sense? Oh, right. There is a way! I forgot about it!
    Code:
    #include <stdstupid_float_magic.h>
    I always forget that!

    [edit]
    Wait wait wait! It's even better! I forgot this one:
    I can't think of a reason I would ever need to do this, but lets pretend
    And you're miffed because some one told you it's undefined. What a ........ing idiot.
    [/edit]

    Quzah.
    Last edited by quzah; 08-23-2005 at 10:00 PM.
    Hope is the first step on the road to disappointment.

  10. #10
    Registered User
    Join Date
    Feb 2002
    Posts
    465
    i am happy to have found a forum that prefers insults over answers.

    first, you are right, macros dont 'return'... I misspoke. what i should have said was, i want what this macro resolves to.

    second, i know that floating point numbers arent stored the same way as integers. i think i made this pretty obvious with how my fake, useless macro worked: the IEEE floating point standard that i as well as most processors use defines a float like this:

    http://www.psc.edu/general/software/...ieee/ieee.html

    performing actions on the bits in a float can hardly be considered magic. adding to the exponent bits results in multiplications by two, similar to the way shifting works in addition. similarly, other operations can be performed on the varioius bits to get certain outcomes. if you think this is "........ing stupid", then you may want to take it up with the people who came up with the standard, not me.

    Seriously. If it's not defined, you have no control over what happens.
    i disagree. assming i know the format that my floats are in, i have every means at hand to make the values exactly what i want them to be.

    all of this badmouthing and insulting aside...

    the only question i had was the one i stated before:

    "how do i put rvalue bits inside of a variable for which bit modification is not allowed by C without creating a temporary variable?"

    whether or not the answer to this question is safe or reliable or portable, i dont care. i want to know if its doable. consider it an excercise of knowlege rather than a viable solution to a problem if you have to...


    oh, and here is some help figuring out what lvalue and rvalue mean, so that in the future you will be able to read my sentances:
    http://cplus.about.com/od/cprogrammi...def_lvalue.htm


    [EDIT]

    there was an error in my stupid little example macro, for those of you who are still looking for things to ridicule me on. it should have went something more like this:

    (0x80000000 | (((exp)&0x000000FF)<<23) | ((mantissa)&0x007FFFFF))

    [/EDIT]
    Last edited by ...; 08-23-2005 at 10:15 PM.
    I came up with a cool phrase to put down here, but i forgot it...

  11. #11
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    i disagree. assming i know the format that my floats are in, i have every means at hand to make the values exactly what i want them to be.
    You can disagree all you like. It doesn't make you right. Floating point numbers are inprecise. Therefore, unless you have memorized every single point at which it decides to round, the best you'll get is "close", which is what floating point numbers are. They're "close". They're not accurate.

    "how do i put rvalue bits inside of a variable for which bit modification is not allowed by C without creating a temporary variable?"
    Well I guess you just answered your own question, didn't you?

    Oh, and the whole "rvalue" issue doesn't exist as far as your not being able to modify it and as to your passing it to a function. When you pass anything to a function, it's automaticly assigned to an lvalue in the call. To use your example:
    Code:
    5.5f = somefunc( ); /* 5.5f is an "rvalue", because it's not a variable, it's a numeric constant */
    somefunc( 5.5f ); /* 5.5f is automaticly a "lvalue" when it reaches the function */
    Anything you pass to this function will automaticly be in an "lvalue" when it gets there. It's impossible to have an "rvalue" reach a function call. Furthermore, were this not a floating point number, you could automaticly mung its bits in the assignment:
    Code:
    somefunc( 5 << 3 );
    So, as stated, to do the same thing to a float, you cast it to an integer first. You can play with void pointers or whatever you like, but the end result is some value ending up stuck in a variable when it reaches the function. It'll get there in a variable. Don't believe me?
    Code:
    #include<stdio.h>
    void foo( float f )
    {
        f = 1.0;
        printf("f is %f\n", f );
    }
    
    int main( void )
    {
        foo( 10.10 );
        return 0;
    }
    There's no such thing as an "rvalue" reaching a function. Ever. It's not going to happen.

    So really, to simply clarify the issue, you could have just asked:

    "Is there any way for me to shift a numeric floating point constants' bits without using a variable or a cast?"

    See how clear that is? Now, a union is going to use a variable. You don't want that. Now you don't want a cast either. Therefore your answer is: no.

    [edit]
    for those of you who are still looking for things to ridicule me on.
    For those of you still looking for a reason to whine, you were the one who turned this into a flame war. Dave simply stated that what you want to do isn't defined by the standard. Then you got your britches in a bunch about it for some reason.
    [edit]


    Quzah.
    Last edited by quzah; 08-23-2005 at 10:37 PM.
    Hope is the first step on the road to disappointment.

  12. #12
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    >> "how do i put rvalue bits inside of a variable for which bit modification is not allowed by C without creating a temporary variable?" <<

    There is no way to take the address of an r-value in C:
    Quote Originally Posted by C89 Draft
    3.3.3.2 Address and indirection operators

    The operand of the unary & operator shall be either a function designator or an lvalue that designates an object that is not a bit-field and is not declared with the register storage-class specifier.
    I think you will have to stick the value in a variable or possibly use assembly.

  13. #13
    Registered User
    Join Date
    Feb 2002
    Posts
    465
    maybe an example will help. bit modification is not allowed directly by C, correct? I will use these macros for the rest of this post:

    #define FBITS(f) (*(int*)&f)
    #define BITSTOF(f) (*(float*)&f)

    but i can still do this:

    #include <stdfloating_point_magic.h>
    float f = 2.0f;
    FBITS(f) |= 0x80000000;

    and suddely, like magic, i have a -2.0f where my 2.0f used to be. so its not true that i cant modify a float's bits with predictable results. so how about this:

    #include <stdfloating_point_magic.h>
    int i = 0x40000000;
    float f = BITSTOF(i);

    again, magically, i get exactly what i wanted, 2.0f.

    but now lets say for some reason i cant have the int, and i must do this directly:

    float f = BITSTOF(0x40000000);

    this obviously doesnt work.

    my question is, is there something that can be done in C that would allow me to get from that hex value to a floating point 2.0f without creating a temporary integer?


    oh, and thanks for that clarification of how function parameters are allocated as memory on the stack. i have a firm grasp of low level floating point manipulation and lvalue/rvalue functionality, but i had no idea how functions work.
    I came up with a cool phrase to put down here, but i forgot it...

  14. #14
    Registered User
    Join Date
    Feb 2002
    Posts
    465
    thank you for keeping it civil, anonytmouse.

    i wanted to avoid assmebly, i have been given enough of a hard time with my portability as it is. were it possible to bust out in assembly, though, it would have been fairly easy, and is how i would normally do it under these circumstances. i was merely curious of the possibility of C supporting this somehow, since it is definitely possible for the processor to do this without creating a temporary variable.
    I came up with a cool phrase to put down here, but i forgot it...

  15. #15
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    Too all:
    Cool the sarcasm. Thank you.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Advantages of c++ type casting over c type casting
    By kaibalya2008 in forum C++ Programming
    Replies: 10
    Last Post: 05-05-2009, 11:09 AM
  2. Casting
    By morvick in forum C++ Programming
    Replies: 2
    Last Post: 06-17-2007, 11:06 PM
  3. casting the system exstracted date into seperate ints
    By bazzano in forum C Programming
    Replies: 1
    Last Post: 08-30-2005, 12:17 AM
  4. Type casting
    By Lionmane in forum C Programming
    Replies: 28
    Last Post: 08-20-2005, 02:16 PM
  5. question about casting pointers/other types also??
    By newbie02 in forum C++ Programming
    Replies: 3
    Last Post: 08-07-2003, 05:01 AM