• Advertisement
Sign in to follow this  

Casting Bytes to Integers (and floats)

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

I believe this is a C++ question, but I will explain why I'm asking this, which is related to networking. Because of the specific nature of the question, I'm posting in "For Beginners" and not "Multiplayer and Networking," as I believe the core problem I'm having is understanding a concept more fundamental than specific networking issues. My program sends and receives data. For the purpose of this post, let's assume I'm sending an integer (four bytes). I cast the integer as a char*, so that I can use Winsock's send() or sendto() function; the parameters of send()/sendto() are the newly-cast integer and the size of the data I'm sending (in this case sizeof(int), or 4). The data is then sent. The program running on my 2nd computer then accepts the data by calling Winsocks recv() or recvfrom() function. recv()/recvfrom() accepts a char* parameter and the size of this char* 's string. So I declare the following: char m_Receive_Buffer[3][128] m_Receive_Buffer has three strings (the first dimension), each with a length of 128 bytes. I send m_Receive_Buffer[0] as the parameter to recv()/recvfrom(), and 128 for the length. So m_Receive_Buffer[0] now has the data I want to recover. My protocol states that the first char or byte in m_Receive_Buffer, or m_Receive_Buffer[0][0], has the length of the message I've sent. So the integer I want to recover starts at m_Receive_Buffer[0][1]. My problem is confusing with C++ pointers, type-casting, etc. Basically, the question is: What is the code to recover the data at m_Receive_Buffer[0][1]?
int x = 0;

// What code goes here so that x == 1025, the value I initially sent?


Thanks. -Gauvir_Mucca EDIT: My original title was an error; I have corrected it. [Edited by - Gauvir_Mucca on July 26, 2006 11:31:33 PM]

Share this post


Link to post
Share on other sites
Advertisement

int *i = reinterpret_cast< int* >(&m_Receive_Buffer[0][1]);
int value = *i;







Something like that would extract your int from the recieve buffer.
(note: code is untested, I can't garuntee it will compile)

Share this post


Link to post
Share on other sites
That will compile, but may not work. reinterpret_cast is a minefield of undefined behaviour. In particular, the number may be reversed due to "endianness" issues, or incorrectly read because of a different size of the int type. If your target and destination computers are basically the same though (hardware manufacturer and OS), there probably won't be an issue there.

More importantly, though, a lot of processors won't let you do an "unaligned read", which is to say, you can't just grab a multi-byte value from any memory address, but only from ones that are a multiple of the value's size.

Fortunately, 'char' is always a 1-byte type, so we can get around the problem by reinterpret_casting the other way: letting the address of an integer (a variable into which the value is read) be interpreted as a byte address, and then doing a byte-for-byte copy into that location:


int x;
char* start = &(m_Receive_Buffer[0][1]);
std::copy(start, start + sizeof(int), reinterpret_cast<char*>(&x));


This of course still does not protect you from the endian and int-size issues.

To deal with endian issues, you can detect the current hardware's endianness, and always send data with a specified endianness; then if they don't match, swap the bytes on the current hardware. However, you don't need to do this yourself: check out the standard library htons()/htonl()/ntohs()/ntohl().

To deal with int-size issues, you'll want some kind of wrapper that guarantees type sizes. These tend to be compiler-specific, but the Boost library can help you out (it provides a header that "knows" the compiler-specific stuff for several different compilers and will wrap it up for you).

Share this post


Link to post
Share on other sites
Thanks for your help - everything works great!

I have just one more question: When sending floats in a similar manner, assuming that I'm not interested in packing the floats into a size less than 4 bytes (as described in the multiplayer forum FAQ), would I have to call an equivalent htonl()/ntohl() functions for floats? I can't seem to find any that work for floats (only for shorts and longs, i.e., 16-bit and 32-bit integers). Is "endianness" not a problem for floats?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement