Is There Any "Standard" Htonl-Like Function for 64 Bits Integers in C++

Is there any standard htonl-like function for 64 bits integers in C++?

You are probably looking for bswap_64 I think it is supported pretty much everywhere but I wouldn't call it standard.

You can easily check the endianness by creating an int with a value of 1, casting your int's address as a char* and checking the value of the first byte.

For example:

int num = 42;
if(*(char *)&num == 42)
{
//Little Endian
}
else
{
//Big Endian
}

Knowing this you could also make a simple function that does the swapping.


You could also always use boost which contains endian macros which are portable cross platform.

Portable way of sending 64-bit variable through POSIX socket

You can just apply htonl() twice, of course:

const uint64_t x = ...
const uint32_t upper_be = htonl(x >> 32);
const uint32_t lower_be = htonl((uint32_t) x);

This will give you two 32-bit variables containing big-endian versions of the upper and lower 32-bit halves of the 64-bit variable x.

If you are strict POSIX, you can't use uint64_t since it's not guaranteed to exist. Then you can do something like:

typedef struct {
uint32_t upper;
uint32_t lower;
} my_uint64;

And just htonl() those directly, of course.

converting 64 bit int from host to network order in c, i get only zeros


void nw_order(const union u *host, union u *net)
{
net -> u32[0] = htonl(net->u32[1]);
net -> u32[1] = htonl(net->u32[0]);
}

You are only using the pointer to net here:

This sets the low 4 bytes to the byte-reversed high 4 bytes and the high four bytes to the twice byte-reversed high 4 bytes <=> to their previous content.

Not what you wanted, right?

Anyway, better do it thus:

uint64_t nw_order(const uint64_t in) {
unsigned char out[8] = {in>>56,in>>48,in>>40,in>>32,in>>24,in>>16,in>>8,in};
return *(uint64_t*)out;
}

This has two advantages:

  • Also works on big-endian (You might not care, if you are only on x86)
  • Does not needlessly use pointers.

Also consider that random() only returns an int, and does not use the full range: Check RAND_MAX. Anyway, this function is not of reliable quality for anything but quick joke-programs.

Using htons() in my code puts all zeros in the buffer and I don't understand why

Converting endianess of a 16 bit number and storing it in a byte array is trivial, there is no need for library functions. Assuming 32 bit CPU:

uint16_t u16 = ...;
uint8_t out[2];

out[0] = ((uint32_t)u16 >> 8) & 0xFFu;
out[1] = ((uint32_t)u16 >> 0) & 0xFFu;

The casts and u suffix are there as a good habits to block implicit promotion to int which is problematic in some cases, since it's a signed number.

Since shifts don't care about the underlying endianess, the above code works for both big-to-little and little-to-big conversions, as long as you go from one to the other.

This scales to 32 bit types as:

uint32_t u32 = ...;
uint8_t out[4];

out [0] = ((uint32_t)u32 >> 24) & 0xFFu;
out [1] = ((uint32_t)u32 >> 16) & 0xFFu;
out [2] = ((uint32_t)u32 >> 8) & 0xFFu;
out [3] = ((uint32_t)u32 >> 0) & 0xFFu;

Is there any conversions when storing/reading integers of different size to/from union?


So is it legal in C++?

No, it isn't legal in c++ (Wikipedia also already stated "While not allowed by C++ ...").

In c++ a union is just reserving memory for the contained union members, such that it is enough to fit the largest member. That memory is shared by all members.

Accessing a different member from the union as was used to initialize it, is undefined behavior. You need to decide beforehand with which union members to work, if these are shared by any functions (this is often done using a type discriminator).



Related Topics



Leave a reply



Submit