-2

I am trying to understand bit and byte manipulation and I have seen many examples in SO. Still, I have some questions regarding my understanding.

First, lets say we have a byte array with the byte order as Least Significant Byte. I want to get the byte 2 from this array. I can get the byte like byte[1]. Am I right?

Second, we have a byte array with the byte order as Least Significant Byte. And I want to get first 2 bits of the byte 1!. How can I get the first 2 bits from that byte? Also, how can I add a number into the first 2 bits of a byte?

Any help or link to understand those logics are much appreciated.

idkman
  • 169
  • 1
  • 15
  • You can bitwise operators like shits (`<<` and `>>`) and `$`. Or you can use *bitfields*. – andresantacruz Aug 21 '19 at 08:59
  • "I can get the byte and use it without any modification right?" this question is unclear to me. What you mean by "get it and use it without any modification"? – andresantacruz Aug 21 '19 at 09:02
  • 2
    Huh, if you have a byte array and you want byte 2 out of it it's either `array[1]` or `array[2]` depending on what you mean by 2 (second or index 2). LSB, MSB is irrelevant because you have a byte array and you want a byte. Please read your question again and check you've used the correct word (bit/ byte) in all places. I think you've mixed them up – Caius Jard Aug 21 '19 at 09:05
  • @CaiusJard Your explanation cleared a part of my confusion, thank you. I think I have written my question correctly. Which part you mean? – idkman Aug 21 '19 at 09:07
  • @Dennis.M the first question is still very unclear and confusing... – andresantacruz Aug 21 '19 at 09:07
  • Note that LSB means least significant _bit_, not byte. Byte order (endianess) only matters in case you try to serialize integers or floats. Otherwise index 0 of a byte array is always the least significant. To mask out bits from a byte, simply use the bitwise operators as advised by your C book. – Lundin Aug 21 '19 at 09:10
  • 2
    More info: [How do you set, clear, and toggle a single bit?](https://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit) – Lundin Aug 21 '19 at 09:11
  • @Lundin Actually, LSB is ambiguous, can stand for [both](https://en.wikipedia.org/wiki/Bit_numbering#Least_significant_byte)... – Aconcagua Aug 21 '19 at 09:13
  • @Aconcagua No, the de facto industry standard meaning is bit. The wikipedia source used in that link is some hobbyist's trash site. – Lundin Aug 21 '19 at 09:15
  • @Lundin Get 2 bits from a byte is `first_2bits = (num >> 6) & 0xFF;`. Am I right? – idkman Aug 21 '19 at 09:21
  • @Dennis.M considering `num` is a 8 bit value and you mean by first 2 bits the most significant bits, yes. – andresantacruz Aug 21 '19 at 09:24
  • @Dennis.M That code gives you the 2 most significant bits, bit number 6 and 7. – Lundin Aug 21 '19 at 09:26
  • @Lundin Any reference for? Have seen counter examples, although not having one by hand at the moment... – Aconcagua Aug 21 '19 at 09:26
  • @Dennis.M `(num >> 6) & 0xff` might give you unexpected results, if `char` is signed on your system and most significant bit is set; `num` will be promoted to `int`, but sign extension occurs, and if right shift is arithmitic shift (usually for signed values), you'll end up in having ones at bit locations 2, 3, ... , 7. If you don't want these, you'd have `(num >> 6) & 0x03`. – Aconcagua Aug 21 '19 at 09:30
  • @Lundin That will give the most significant bits, if the bit order is most significant bit. If the bit order is least significant bit, it will give the 2 least significant bits. Is my understanding correct? – idkman Aug 21 '19 at 09:32
  • 2
    @Dennis.M There only exists one bit order on all computers. Bit 7 is always the MSB. – Lundin Aug 21 '19 at 09:34
  • @Lundin Then why there is `Most Significant Bits` and `Least Significant Bits`. I didn't get. – idkman Aug 21 '19 at 09:36
  • Because on a 16 bit word the MSB is number 15, on a 32 bit word MSB is number 31 and so on. – Lundin Aug 21 '19 at 09:39
  • @Lundin Cleared! – idkman Aug 21 '19 at 09:40
  • @Dennis.M LSB/MSB can play an important role, though, if you have protocols based on serial transmission (i. e. only one bit at a time), such as SPI, I²C, 1-wire, ... If you only transmit one bit at a time, *then* you need to know if first bit transmitted is LSB or MSB! – Aconcagua Aug 21 '19 at 10:07

1 Answers1

2

First, lets say we have a byte array with the byte order as LSB. I want to get the byte 2 from this array. I can get the byte like byte[1]. Am I right?

Yes.

Second, we have a byte array with the byte order as LSB. And I want to get first 2 bits of the byte 1!. How can I get the first 2 bits from that byte? Also, how can I add a number into the first 2 bits of a byte?

You can use the bitwise AND operator & with the constant 3 to retrieve only the first two bits. By doing num & 3 it will realize a condition operation between each bit of num and 3 returning 1 as resultant bit only if both bits are 1. As 3 have only its 2 first bits set, every bit in num other than the first 2 will be ignored.

unsigned char foo = 47;
unsigned char twobits = foo & 3; // this will return only the value of the two bits of foo.
unsigned char number_to_add = 78;
twobits &= (number_to_add & 3); // this will get the values of the 2 bits of number_to_add_ and then assign it to the 2 bits of variable twobits.

Or if you don't care of the endianess you can use bitfields:

struct st_foo
{
     unsigned char bit1 : 1;
     unsigned char bit2 : 1;
     unsigned char the_rest : 6;
};

struct st_foo my_byte;
my_byte.bit1 = 1;
my_byte.bit2 = 0;
andresantacruz
  • 1,676
  • 10
  • 17
  • There's no guarantee that "bit1" in your bit-field example is the LSB. Furthermore, bits are always enumerated from 0 to 7, not from 1 to 8. – Lundin Aug 21 '19 at 09:32
  • Also, `unsigned char` need not be a valid type to be used for bit-fields, it isn't guaranteed to work by the standard. Your example relies on compiler-specific extensions. – Lundin Aug 21 '19 at 09:36
  • @Lundin I don't think if I got it. C standard doesn't rules bit-fields? Please elaborate a bit more. – andresantacruz Aug 21 '19 at 09:38
  • @Lundin so if I understood well I could use `st_foo` to be treated as a 8 bit value but could not count on the bit ordering? That means any code that relies on bit-field structures are implementation-specific? – andresantacruz Aug 21 '19 at 10:33
  • 1
    No, you can treat it as a chunk of binary, containing 3 other chunks of binary, in unspecified order. Yes, code that uses bit-fields is very implementation-specific and completely non-portable, while at the same time not offering any advantages. – Lundin Aug 21 '19 at 10:36
  • @Lundin got it, thanks for the clarification, but don't you think a code that uses bit-fields are more readable than one relying on shifts and other bitwise operators (considering the bit ordering is not important)? – andresantacruz Aug 21 '19 at 10:39
  • 1
    Bitwise operations are so incredibly common that they _should_ be readable to any C programmer. Long as the number of operations on a single line are kept low. – Lundin Aug 21 '19 at 10:41