6

the following is the IP structure from library on a linux machine

   struct ip
      {
    #if __BYTE_ORDER == __LITTLE_ENDIAN
        unsigned int ip_hl:4;               /* header length */
        unsigned int ip_v:4;                /* version */
    #endif
    #if __BYTE_ORDER == __BIG_ENDIAN
        unsigned int ip_v:4;                /* version */
        unsigned int ip_hl:4;               /* header length */
    #endif
        u_int8_t ip_tos;                    /* type of service */
        u_short ip_len;                     /* total length */
        u_short ip_id;                      /* identification */
        u_short ip_off;                     /* fragment offset field */
    #define IP_RF 0x8000                    /* reserved fragment flag */
    #define IP_DF 0x4000                    /* dont fragment flag */
    #define IP_MF 0x2000                    /* more fragments flag */
    #define IP_OFFMASK 0x1fff               /* mask for fragmenting bits */
        u_int8_t ip_ttl;                    /* time to live */
        u_int8_t ip_p;                      /* protocol */
        u_short ip_sum;                     /* checksum */
        struct in_addr ip_src, ip_dst;      /* source and dest address */
      };

for these lines:

    #if __BYTE_ORDER == __LITTLE_ENDIAN
        unsigned int ip_hl:4;               /* header length */
        unsigned int ip_v:4;                /* version */
    #endif
    #if __BYTE_ORDER == __BIG_ENDIAN
        unsigned int ip_v:4;                /* version */
        unsigned int ip_hl:4;               /* header length */
    #endif

why endianess matters inside a byte? I think endianess only affect multi-byte integers, but here it seems to me that endianess also affect bits arrangement inside a byte?

besides, it is only a byte, why it is unsigned int, which is 4 bytes.

I notice in wireshark, ip_v and ip_hl is shown as 0x45 If I capture an IP packet. The first byte is composed of ip_v and ip_hl I put it into a character variable x

then what is the result of x & 0b11110000 ? is it always 4 no matther what endianess, or it may be 5?

misteryes
  • 2,167
  • 4
  • 32
  • 58
  • possible duplicate of [Why does an 8-bit field have endianness?](http://stackoverflow.com/questions/864077/why-does-an-8-bit-field-have-endianness) – Sergey Kalinichenko May 16 '13 at 00:49
  • what is the result of x & 0b11110000 ? is it always 4 no matther what endianess, or it may be 5? – misteryes May 16 '13 at 01:12
  • Yes, the result of `0x45 & 0b1110000` is always `0x40`, no matter what the endianness is. However, bit fields (the "colon four" `:4` things) can be placed in either order by the compiler. So if you assign `ip_hl=4, ip_v=5` you could get `0x45` or `0x54`, depending on the compiler (and compilers often follow the endianness of the bytes when deciding the endianness of nibbles). – Sergey Kalinichenko May 16 '13 at 01:21

2 Answers2

3

There is byte ordering which is relevant in case of multiple byte data. But in your case what matters is bit field ordering, which deals with the order of bits in case of a single byte data. There are no rules put forward by the C standard regarding bit field ordering. It is implementation dependent and decided by the compiler.

The size of the variable is not 4 bytes. It is just 4 bits. They are not independent variables. They are bit fields inside a structure.

Deepu
  • 7,592
  • 4
  • 25
  • 47
  • it is only one byte, why it is type of unsigned int, which is 4 bytes. – misteryes May 16 '13 at 01:08
  • 1
    "unsigned int" followed by the colon and an integer, as in "unsigned int ip_v:4", is the declaration of a bit field. If it helps, think of it as an "unsigned int which is 4 bits in size" (except that, strictly speaking, no other type can be used when declaring a bit field). – Luis May 16 '13 at 01:28
2

The endianess defines the place of the Most Significant Bit (MSB), it is related to the way the number inside a variable is interpreted in memory. Considering unsigned integers:

00000001 (Binary) = 1 (2 to the power of 0) -> If the most significant bit is to the left

00000001 (Binary) = 128 (2 to the power of 7) -> If the most significant bit is to the right

As you can see the position of the most significant bit is very important when it comes to the number representation in memory, even in 8 bit numbers.

For your last question you are right, it makes no difference if it is 1 byte or 4 because it is taking only 4 bits. But but remember that an unsigned int not always is a 4 bytes number.

Hope it helps!

Sergio Ayestarán
  • 5,590
  • 4
  • 38
  • 62
  • how about `then what is the result of x & 0b11110000 ? is it always 4 no matther what endianess, or it may be 5?` I'm really very confused about this – misteryes May 16 '13 at 12:41
  • 2
    This is misleading. As far as C is concerned, binary `00000001` (`0x01`) is **always** `1` in base 10. For instance, the **right shift** operator `>>` cuts (positive) numbers (roughly) in half, it doesn't double them: `4>>1 == 2`. As others have pointed out, the endianess is of **bit fields**. §6.7.2.1, paragraph 11 of the standard states that the `order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined.` – jerry May 16 '13 at 18:35
  • But the question was not about the endianess in C, and yes of course, it is expected in almost all computer languages for the same instruction to behave in the same way in different hardware. If you pay attention to the code it seems to be dealing with data from a hardware interface -> different hardware can have different endianess -> endianess matters – Sergio Ayestarán May 16 '13 at 23:30
  • 1
    The question is about endianness in C, hence the C code and tag. In standard C, you can't address specific bits. The only way to access them directly is with shifts, bitwise operations, and bit fields. The standard mandates that numbers appear as if the MS bit is "first". It is the translator's responsibility to ensure this no matter the bit-order of the underlying hardware (if that even applies). Bit fields may start at either end, but the result value is still MSB-first. Network and comm protocols may be transmitted LSB-first, but that doesn't mean that's how they're stored or accessed in C. – jerry May 20 '13 at 14:59
  • This answer is simply incorrect. See http://stackoverflow.com/questions/864077/why-does-an-8-bit-field-have-endianness and Deepu's answer below. Endianness as a concept does not generally pertain to the ordering of bits, but certain implementations may flip the bit order based on endianness, just out of their own discretion. – OldPeculier Jun 26 '14 at 16:16
  • Oh Lord, 1st: the question is about why endianess matters inside a bit, and it doesn't matter what you think or the tag of the question if you don't consider endianess when dealing with low level hardware your code will not work, 2nd Thanks, that guy is stating the same thing I did, this is not a discussion about the C compiler, as I said the compiler must have the same behavior on different hardware, but if your program interfaces with another piece of hardware (i.e. not the pc where you are developing) in some cases you need to consider endianess. – Sergio Ayestarán Jun 26 '14 at 18:55