# C union float trick?

This topic is 4708 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm looking through the Quake3 networking code and I come accross this:
void MSG_WriteFloat( msg_t *sb, float f ) {
union {
float	f;
int	l;
} dat;

dat.f = f;
MSG_WriteBits( sb, dat.l, 32 );
}
void MSG_WriteChar( msg_t *sb, int c ) {
#ifdef PARANOID
if (c < -128 || c > 127)
Com_Error (ERR_FATAL, "MSG_WriteChar: range error");
#endif

MSG_WriteBits( sb, c, 8 );
}
void MSG_WriteLong( msg_t *sb, int c ) {
MSG_WriteBits( sb, c, 32 );
}


The function I'm wondering about is MSG_WriteFloat... they declare a union, assign something to the float, and then send the int?! Why do they do this? Wait, I just realized I should look at the read function...
int MSG_ReadLong( msg_t *msg ) {
int	c;

c = MSG_ReadBits( msg, 32 );
if ( msg->readcount > msg->cursize ) {
c = -1;
}

return c;
}

float MSG_ReadFloat( msg_t *msg ) {
union {
byte	b[4];
float	f;
int	l;
} dat;

dat.l = MSG_ReadBits( msg, 32 );
if ( msg->readcount > msg->cursize ) {
dat.f = -1;
}

return dat.f;
}

Again...they assign something to the int, but return the float??? I don't get it. How can they work with floats by using ints in a union variable? Thanks for the help, Darrell

##### Share on other sites

CPlusPlus.com tutorial

The portion on unions will explain why.

##### Share on other sites
The read bits and write bits functions take ints (not floats). And with a union all the different possible objects share the same piece of memory (so changing one will change the others). And on the system they're using (x86) sizeof(float)=sizeof(int).

Edit ask if you need a clarification on the above, my description is terse.

##### Share on other sites
Just a warning...according to the C++ Standard assigning one type of a union and then reading another is undefined. Most compilers do what you would probably want/expect, but it would still be perfectly valid for an app to crash then.

##### Share on other sites
This is in fact illegal C++ (not sure about C), however most compilers support it because it's a common trick. The reason is that compilers can optimize by assuming variables of different types cannot alias to the same memory location, but in this case it's fairly easy for the compiler to handle.

Edit: beaten.

##### Share on other sites
The correct C++ way to do this would be to reinterpret_cast it to a float. In C, usually you would use *(int*)&f.

##### Share on other sites
Quote:
 Original post by PromitThe correct C++ way to do this would be to reinterpret_cast it to a float. In C, usually you would use *(int*)&f.
Are you sure? I thought such reinterpret_casts were implementation defined? Wouldn't the proper method be to use a binary steam's operator <

##### Share on other sites
(continued due to crappy handling of angled brackets in AP posts)
a binary stream's insertion operator? Is there a binary (in the file as text vs binary sense) equivalent of stringstream that could be used to convert POD types to some type of byte buffer?
-Extrarius

##### Share on other sites
Quote:
 Original post by PromitThe correct C++ way to do this would be to reinterpret_cast it to a float.

Really? In MSVC++7,

int i = 10;float j = reinterpret_cast<float>(i);

gives me:

error C2440: 'reinterpret_cast' : cannot convert from 'int' to 'float'

##### Share on other sites
Quote:
Original post by bakery2k1
Quote:
 Original post by PromitThe correct C++ way to do this would be to reinterpret_cast it to a float.

Really? In MSVC++7,

int i = 10;float j = reinterpret_cast<float>(i);

gives me:

error C2440: 'reinterpret_cast' : cannot convert from 'int' to 'float'

You would use pointers.

1. 1
2. 2
3. 3
4. 4
Rutin
12
5. 5

• 12
• 16
• 10
• 14
• 10
• ### Forum Statistics

• Total Topics
632659
• Total Posts
3007691
• ### Who's Online (See full list)

There are no registered users currently online

×