1

I was trying to write signed integer value in a file in big endian.

I'm using this code :

int32_t swap_int32( int32_t val )
{
    val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF ); 
    return (val << 16) | ((val >> 16) & 0xFFFF);
}

It works fine with negative value but I've some issues with positive value :

-5 gives me :

$> hexdump OUTPUT
ff ff ff fb

Which is correct

but 1337 gives me :

  $> hexdump OUTPUT
     00 00 05 39

Instead of (expected) 00 00 39 05.

Is there anyway to treat both cases and get correct result ? Thanks you.

r3dalice
  • 119
  • 2
  • 10

4 Answers4

3

Is there some problem with using htonl?

   #include <arpa/inet.h>

   uint32_t htonl(uint32_t hostlong);

The values in the bytes should stay the same, so even though you want a signed value and htonl take an unsigned as long as you read it back into a signed type you shouldn't lose data. (As noted by mctylr, network order is big-endian.)

#include <arpa/inet.h>
#include <stdio.h>

int main(int argc, char** argv) {
  int32_t pos = 1337;
  int32_t neg = -123;
  printf("host-endian:  %d => 0x%08x  %d => 0x%08x \n", 
         pos, pos, neg, neg);

  uint32_t big_endian_pos = htonl(pos);
  uint32_t big_endian_neg = htonl(neg);

  printf("Big-endian:   %d => 0x%08x %d => 0x%08x \n", 
         pos, big_endian_pos, neg, big_endian_neg);

}

And the output on my little-endian host:

[tmp]$ gcc endian.c  && ./a.out 
host-endian:  1337 => 0x00000539  -123 => 0xffffff85 
Big-endian:   1337 => 0x39050000  -123 => 0x85ffffff 
Paul Rubel
  • 26,632
  • 7
  • 60
  • 80
  • To clarify, *network byte order* is **big** endian. So on either an little endian or big endian host (system), the network long (unsigned 32-bit integer) is written in big endian byte ordering. – mctylr Dec 16 '11 at 17:19
1

At a minimum, you should cast to "unsigned" inside your function.

As an alternative, you can always use the network macros "htons()" (16-bit) and "htonl()" (32-bit) to convert host to network (big-endian) byte order.

paulsm4
  • 114,292
  • 17
  • 138
  • 190
  • Good point. `x >> y` might be an arithmetic shift when `x` is signed, depending on the compiler: http://stackoverflow.com/questions/7622/shift-operator-in-c – bk1e Dec 16 '11 at 18:00
0

Network byte order is big endian.

POSOX UNIX has htonl(), htons() and friends to do just what you require. They guarantee big endian from any system.

jim mcnamara
  • 16,005
  • 2
  • 34
  • 51
0

On *BSD and Linux systems you can use byteorder(9) functions including bswap_32() when used on a little endian host.

#include <sys/endian.h>  /* other platforms may need: sys/param.h endian.h or byteswap.h */
#include <stdint.h>

uint32_t in, out;

out = bswap_32(in);

On little endian MS Windows systems, _byteswap_ulong is included in stdlib.h, even though it is not standard.

Otherwise various bit twiddling examples can be easily found across the Internet.

And StackOverflow

  • convert big endian to little endian in C {without using provided func} 2182002
  • How do I convert between big-endian and little-endian values in C++? 105252
  • Fast little-endian to big-endian conversion in ASM 1358747 - 2 out of 3 answers are not C# oriented
Community
  • 1
  • 1
mctylr
  • 5,159
  • 20
  • 32