2

I'm referring to the following code:

u_int32_t htonl(u_int32_t x)
{
#if BYTE_ORDER == LITTLE_ENDIAN
    u_char *s = (u_char *)&x;
    return (u_int32_t)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
#else
    return x;
#endif
}

For example:

unsigned int x = 0x01020304

in little ending system:

s[0] = 0x04, s[1] = 0x03, s[2] = 0x02, s[3] = 0x01

then return:

(u_int32_t)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);

the return value, for example:

u_int32t_t result = (u_int32_t)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);

in the system memory:

u_char *r = (u_char *)&result

so:

r[0] = 0x04, r[1] = 0x03, r[2] = 0x02, r[3] = 0x02

Is this correct?

honk
  • 9,137
  • 11
  • 75
  • 83
user2309793
  • 55
  • 1
  • 6

1 Answers1

4

The purpose of htonl is to convert value representation to network byte order - big endian. Let's suppose that you're working on intel machine and your byte order is little endian (the code in if statement is executed). You could write a dummy code that checks your understanding how it works:

#include<stdio.h>
#include <stdlib.h>
int main()
{
    u_int32_t x = 16909060;  //0x01020304
    u_char* s = (u_char*)&x;
    printf("%x\n",x);
    printf("s[0]: %x\n",s[0]);
    printf("s[1]: %x\n",s[1]);
    printf("s[2]: %x\n",s[2]);
    printf("s[3]: %x\n",s[3]);
    printf("s[0] << 24: %x\n", s[0] << 24);
    printf("s[1] << 16: %x\n", s[1] << 16);
    printf("s[2] << 8: %x\n", s[2] << 8);
    printf("final: %x\n", s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);

    return 0;
}

output:

1020304
s[0]: 4
s[1]: 3
s[2]: 2
s[3]: 1
s[0] << 24: 4000000
s[1] << 16: 30000
s[2] << 8: 200
final: 4030201

OR operator has following truth table:

a b out
0 0  0
0 1  1
1 0  1
1 1  1

so here's the calulation

0000 0100 0000 0000 0000 0000 0000 0000 |   //s[0] << 24
0000 0000 0000 0011 0000 0000 0000 0000 |   //s[1] << 16
0000 0000 0000 0000 0000 0010 0000 0000 |   //s[2] << 8
0000 0000 0000 0000 0000 0000 0000 0001 =   //s[3]
_________________________________________

0000 0100 0000 0011 0000 0010 0000 0001     

To summarize, 0x01020304 in different byte orders:

  • little endian: 04 03 02 01 (LSB has the smallest address)
  • big endian: 01 02 03 04 (MSB has the smallest address)
macfij
  • 3,093
  • 1
  • 19
  • 24
  • so,the return value int x = 0x4030201,in the memory,eg,u_char* s = (u_char*)&x; s[0] = 0x01,s[1] = 0x02,s[2] = 0x03,s[3] = 0x04? – user2309793 Sep 07 '14 at 08:57