Thread: casting non-lvalues

  1. #16
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    >> 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? <<

    No.

    >> since it is definitely possible for the processor to do this without creating a temporary variable. <<

    I'm only an assembler novice, but I would have thought that 0x40000000 would be placed in an integer register and would have to be placed elsewhere to be treated as a float. [edit]I suppose you may be able to copy the value directly from the register to the calling stack, missing the temporary variable required in C.[/edit]
    Last edited by anonytmouse; 08-23-2005 at 11:18 PM.

  2. #17
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by ...
    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.
    Guess what, idiot? You no longer have a floating point number. You turned it into an integer with a cast. The very thing you said you didn't want.

    Furthermore, your macro fails with a true rvalue. Stop passing it lvalues. In none of these examples are you tweaking the "bits of an rvalue". You're always tweaking the bits of an lvalue. Which is the opposite of what you said you actually wanted to do. Don't believe me? I'll prove it. Compile this. I dare you.
    Code:
    #include<stdio.h>
    
    #define FBITS(f) (*(int*)&f)
    
    int main( void )
    {
        float f;
    	
    	f = FBITS( 2.0 );
        return 0;
    }
    /*
    gcc -o moron moron.c -Wall -pedantic -ansi
    
    moron.c: In function `main':
    moron.c:9: error: invalid lvalue in unary `&'
    */
    I can hear you now: "But it said lvalue smart ass! I thought you said rvalue! HAH!"

    I did. You cannot manipulate an rvalue. Therefore, any manipulation must be turned into... wait for it... an lvalue! As you've already been told by anon.

    So, what if I pass it f instead? Well, that's not changing an rvalue! It's changing an lvalue! You've already been told you can't tweak an rvalue. Now you've been shown again. Still feel like proving yourself wrong? Go ahead.

    Oh, and apparently in your great wisdom, you've forgotten the simplest way to get a "negative float":
    Code:
    foo = 0.0f - wtfe;
    Can't see the forest for the trees, eh brainy?

    i have a firm grasp of low level floating point manipulation and lvalue/rvalue functionality, but i had no idea how functions work.
    No dude, you truely don't have a ........ing clue.

    Quzah.
    Hope is the first step on the road to disappointment.

  3. #18
    Banned
    Join Date
    Jun 2005
    Posts
    594
    you forced him to use cuss words, uh oh.

  4. #19
    Registered User
    Join Date
    Feb 2002
    Posts
    465
    I am going to finish up this thread with one final statement in my defense, and then i will not reply to it again.

    the examples that i specified work, as i said they did, and the last example doesnt work, exactly like i said. I was showing you what worked and what didnt work, in the hopes that all of your anger and frustration came from you not understanding the question. i know what an lvalue is, i know what an rvalue is, i know how floats work. of course you cant put a 2.0f in FBITS, i already said that didnt work with the hex number i used in the final example. thats the reason that i posted in the first place; i know assembly can do it, i wanted to know if, through some strange way, C could do it.

    I already got the best answer I am going to get and a hell of a lot else besides, so I am officially done asking. Thank you to everyone that didnt get involved in all of the pettiness. Go ahead and get the last word, I'm sure you had a few insults that youve been saving for this moment. perhaps involving my mother?

    (and to think, i used to recommend this place to people).


    [edit to anonytmouse]
    you can freely move values from integer registers into floating point variables in memory, as long as they are the same size as the variable you are writing to. here is an example from some "fast squareroot" code that i picked up a while back:

    #define ASM_SQRT(float_num, float_answer)\
    __asm mov eax, float_num \
    __asm sub eax, 0x3f800000 \
    __asm sar eax, 1 \
    __asm add eax, 0x3f800000\
    __asm mov float_answer, eax

    (compiles in visual studio)

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

  5. #20
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    you can freely move values from integer registers into floating point variables in memory, as long as they are the same size as the variable you are writing to. here is an example from some "fast squareroot" code that i picked up a while back:
    Code:
    #define ASM_SQRT(float_num, float_answer)\
    __asm mov eax, float_num \
    __asm sub eax, 0x3f800000 \
    __asm sar eax, 1 \
    __asm add eax, 0x3f800000\
    __asm mov float_answer, eax
    (compiles in visual studio)
    But you've still got the one copy operation to get from an int to a float: __asm mov float_answer, eax. Won't the C code result in much the same thing?
    Code:
    int fake_float = 0x40000000;
    // Use fake_float as a float using your #define BITSTOF(f) (*(float*)&f) macro
    As I mentioned in my edit, if you wanted to pass 0x40000000 directly to a function you may be able to avoid a temp variable by using assembler.
    [edit]
    I compiled this with GCC:
    Code:
    #include <stdio.h>
    
    #define BITSTOF(f) (*(float*)&f)
    
    void printfloat(float f)
    {
    	printf("%.2f\n", f);
    }
    
    int main(void)
    {
    	int fake_float = 0x40000000;
    	printfloat(BITSTOF(fake_float));
    	getchar();
    }
    and got this (the interesting bit):
    Code:
    	subl	$12, %esp
    	pushl	$0x40000000
    	call	_printfloat
    So it appears the compiler is smart enough not to use a temporary variable.
    [/edit]
    This sort of stuff is likely to defeat the optimiser, so I'd want to be sure that there is an actual performance improvement that is worth the bother.
    Last edited by anonytmouse; 08-24-2005 at 12:02 AM.

  6. #21
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Well, I'm an ass, everyone knows that. But at any rate, here we go:

    Your first post, I did misread, which is why you got the answer of turning whatever your macro returned into a float by adding 0.0f to it. However, reading this line again:
    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?
    And you see where my answer comes from:
    Code:
    foo( 0.0f + YOURMACRO( ... ) );
    It's now a float. Even an rvalue is turned into a float with that. (float + anything) is in fact a float. What you apparently wanted was to manipulate the bits of an rvalue, which isn't what you ask in that question. You say "turn this rvalue into a float". I did. I turned it directly into a float. You didn't say: "Turn this value into the bits of a floating point number." Which is something entirely different.

    You have a macro which returns the "rvalue" of 5. You may as well say:
    Code:
    #define FOO 5
    for all intents and purposes. Ok, now you say: "Is there any way, given the setup or similar setup of code, that would allow me to convert the non-lvalue integer [sic]return of a macro directly into a float without casting?" Sure. Here:
    Code:
    bar( 0.0f + FOO );
    Didn't that do what you asked? Sure looks like a floating point number to me.

    Quote Originally Posted by Dave_Sinkula
    IMO, such things tend to assume too much about the implementation and should be shunned. Such behavior is undefined.
    Dave's opinion (IMO see that? IMO...) is that you should avoid such things. You don't like Dave's opinion. You also don't like my wording, or my solution, version, whatever:
    Quote Originally Posted by ...
    wow, lotta testy people today...

    the only thing thats broken about that is your assumptions...
    If your macro wasn't broken, why ask the question? Nevermind.

    Then you also add more information:
    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.
    You don't specificly say that in your first post. See how it pays to be clear? Oh, also, "standard 32bit floats and its" aren't standard. The standard does not say an int has to be 32 bits. It doesn't even say floats have to be 32 bits. All it ever sets are minimums. But I'm sure you knew that.

    Dave replies again, because as I mention, you didn't specify at the time anything about what you needed other than you wanted some hackish fix for rvalues (if we stretch your question a bit).
    Quote Originally Posted by Dave_Sinkula
    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.
    You don't state at all in your first post anything about IEEE floating point standards, which is what Dave had to go by at the time of his post.

    Then I rant a bit about how I think you're an idiot for a while. But in the midst of that, I show you the simplest way to make your negative float, which you apparently didn't see, or didn't like. But the fact is, it's the easiest way to do it, rvalue or no.

    Then you follow up with how you really can manipulate the bits of a floating point number, which is wrong.
    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.
    No it doesn't. You're wrong. You cannot preform bitwise operations on floating point numbers. Period. It doesn't matter what you say to this, you're wrong.

    No, wait, you think you can:
    #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:
    But you're wrong. At this point it's really sad. See, I wasn't even starting this post to flame you. I was starting it to simply walk through the thread, say I was wrong and an ass, but also to step through the thread.

    But at this point, you are clearly wrong, and you can't even see it. You cannot manipulate the bits of a floating point number. It doesn't happen. The only way you can even remotely pretend to do so, is because you typecast it to an integer. Then, it's no longer a floating point number! You're operating on an integer. The language doesn't let you manipulate the bits of a floating point number, because there is no C standard way to store them. That's why you can't do it. That's why you have to fake it with a cast. And no, you cannot fully get the exact results you want. It's impossible. Oh, sure, for some numbers it may turn out so it looks right, but it is not accurate, for the simple fact that floating point numbers aren't accurate. It's impossible to have high precision accurate floating point numbers. IT doesn't happen.

    Your manipulation isn't of a float, it's of an integer. It's no longer a float... now I'm just being redundant.

    Then you're told that you can't get the address of an rvalue. Which means you can't manipulate them directly.

    Then I tell you you're an idiot few more times, and that you still don't know what you're talking about. You say you do, and at the time of this post, it's quite clear you still don't. But you're done replying apparently, except you really aren't, because you're editing your post as I write...

    In short, I'm an ass, everyone knows it, and you still don't know what you're talking about. But at least you know something, which is that no, you can't get the address of an rvalue.


    Quzah.
    Last edited by quzah; 08-23-2005 at 11:58 PM. Reason: Typo. Wouldn't want them to complain about that too, would we?
    Hope is the first step on the road to disappointment.

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