Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

send int over socket: signed vs unsigned

Tags:

c++

c

Say I want to send 4 byte integer over network. The integer has fixed size, due to using types from stdint. My question is: Does it matter if I try to send either signed or unsigned integer using these 4 bytes? (assuming I use same method to serialize/deserialize the integer to/from bytes, both on client and server side). Can there be some other problems? (I don't refer to endianness issues either)


2 Answers

This issue seldom gets the attention it deserves.

As Floris observes, only the bytes of the representation get sent. C and C++ define the bitwise representation* of unsigned numbers, but not signed ones, so sending signed numbers as bytes opens a compatibility gap.

It's easy to "fix" the format for transmission. Casting a signed int to its corresponding unsigned type is guaranteed to generate two's complement representation. But how to convert back? Casting an unsigned integer to its signed counterpart generates signed integer overflow when you want a negative number, which produces an unspecified result — you could get anything.

To be really safe, use a branch:

signed int deserialize_sint( unsigned int nonnegative ) {
    if ( nonnegative < INT_MAX ) return nonnegative;
    else return - (int) ( - nonnegative ); // Only cast an unsigned number < INT_MAX
}

With luck, the compiler will see that both cases are the same and eliminate the branch.

The above function is written in C; apologies to the C++ crowd.

If you want to be extra paranoid, you could check - nonnegative < INT_MAX before performing the cast, because the most negative number in a two's complement will still overflow a one's complement machine. The best you can do for the case of nonnegative == - nonnegative is to return a wider type, or if that's impossible, flag a runtime error.

* Endianness becomes ambiguous when the bits are divided into a byte sequence, though.

like image 95
Potatoswatter Avatar answered Aug 01 '26 22:08

Potatoswatter


Because the standard does not mandate a particular representation for signed types:

3.9.1 Fundamental types [basic.fundamental] Paragraph 7 of n3936

Types bool, char, char16_t, char32_t, wchar_t, and the signed and unsigned integer types are collectively called integral types. A synonym for integral type is integer type. The representations of integral types shall define values by use of a pure binary numeration system. [ Example: this International Standard permits 2’s complement, 1’s complement and signed magnitude representations for integral types. —end example ]

Sending signed integer values in a binary representation is not well defined (unless you explicitly specify this as part of your protocol and do some manual work to make sure you know how to read/write that binary representation).

There are a couple of solutions depending on the exact requirements.

  • If speed is not primary concern then you could use an English (substitute language of your choice) representation and serialize integers to/from text. For a lot of problems this is not a bad solution as the major speed bump is not the serialization cost but network latency. Network latency is the major problem in most situations (but not always).
  • So alternatively if you need binary representation (because you timed it and the volume/density of your numbers requires it). Then the endianess problem is not hard to solve because of htonl() and family. Which covers all unsigned integral types (well at least 16/32 bit values).
    • So all you really need to solve is the representation of signed values. So pick one (Use the most common representation for the machines you use and the translation will then usually be a no-op). But if you know the on the wire representation (because it is specified in your protocol), then you can translate to/from this representation (usually this cost is small (a conditional addition)) on machines that do not natively support this representation.
like image 29
Martin York Avatar answered Aug 01 '26 22:08

Martin York



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!