6

We need to support 3 hardware platforms - Windows (little Endian) and Linux Embedded (big and little Endian). Our data stream is dependent on the machine it uses and the data needs to be broken into bit fields.

I would like to write a single macro (if possible) to abstract away the detail. On Linux I can use bswap_16/bswap_32/bswap_64 for Little Endian conversions.

However, I can't find this in my Visual C++ includes.

Is there a generic built-in for both platforms (Windows and Linux)?

If not, then what can I use in Visual C++ to do byte swapping (other than writing it myself - hoping some machine optimized built-in)?

Thanks.

alk
  • 69,737
  • 10
  • 105
  • 255
user626201
  • 1,623
  • 3
  • 19
  • 36

3 Answers3

13

On both platforms you have

for short (16bit): htons() and ntohs()

for long (32bit): htonl() and ntohl()

The missing htonll() and ntohll() for long long (64bit) could easily be build from those two. See this implementation for example.

Update-0:

For the example linked above Simon Richter mentions in a comment, that it not necessarily has to work. The reason for this is: The compiler might introduce extra bytes somewhere in the unions used. To work around this the unions need to be packed. The latter might lead to performance loss.

So here's another fail-safe approach to build the *ll functions: https://stackoverflow.com/a/955980/694576

Update-0.1:

From bames53' s comment I tend to conclude the 1st example linked above shall not be used with C++, but with C only.

Update-1:

To achieve the functionality of the *ll functions on Linux this approach might be the ' best'.

alk
  • 69,737
  • 10
  • 105
  • 255
  • Those functions are relatively universal for any OS that understands networks (ie internet). Some most modern OSs. – Martin York Oct 18 '12 at 17:31
  • Note that their example implementation using `union` is not guaranteed to work. – Simon Richter Oct 18 '12 at 17:34
  • Yes, you are right the unions should be packed. Thanks for pointing this out. Please see the update to my answer. @SimonRichter – alk Oct 18 '12 at 17:39
  • The issue with using unions like that isn't just packing. In C++ using unions like that is undefined behavior; the optimizer could legally transform `union { int x, y; } u; u.x = 5; return u.y;` into `return 0;`, for example. – bames53 Oct 18 '12 at 18:24
  • Thank you, this is an interesting point, which I wasn't aware of, but surely can imagine. You might have any citation for this? @bames53 – alk Oct 18 '12 at 18:54
  • 1
    [class.union] 9.5/1, or there's a more thorough explanation in [this question](http://stackoverflow.com/questions/10271929/union-for-uint32-t-and-uint8-t4-undefined-behavior). – bames53 Oct 18 '12 at 19:01
  • Actually, here's a better one: http://stackoverflow.com/questions/11373203/accessing-inactive-union-member-undefined – bames53 Oct 18 '12 at 19:04
2

Not the same names, but the same functionality does exist.

EDIT: Archived Link -> https://web.archive.org/web/20151207075029/http://msdn.microsoft.com/en-us/library/a3140177(v=vs.80).aspx

_byteswap_uint64, _byteswap_ulong, _byteswap_ushort

user93353
  • 13,733
  • 8
  • 60
  • 122
2

htons and htonl (and similar macros) are good if you insist on dealing with byte sex.

However, it's much better to sidestep the issue by outputting your data in ASCII or similar. It takes a little more room, and it transmits over the net a little more slowly, but the simplicity and futureproofing is worth it.

Another option is to numerically take apart your int's and short's. So you & 0xff and divide by 256 repeatedly. This gives a single format on all architectures. But ASCII's still got the edge because it's easier to debug with.

user1277476
  • 2,871
  • 12
  • 10
  • Would love to do that, but we don't control the transmission. It is data read in from a special hardware device, and need to handle the bytes from there. – user626201 Oct 19 '12 at 06:58