Lactobacillus
Lactobacillus

Reputation: 47

how to split 16-value into two 8-bit values in C

I don't know if the question is right, but.

Example, a decimal of 25441, the binary is 110001101100001. How can i split it into two 8 bit "1100011" and "01100001"( which is "99" and "97"). However, I could only think of using bit manipulation to shift it by >>8 and i couldn't do the rest for "97". Here is my function, it's not a good one but i hope it helps:

void reversecode(int input[], char result[]) {  //input is 25441
int i;
for (i = 0; i < 1; i++) {  
    result[i] = input[i] >> 8;                  // shift by 8 bit
    printf("%i", result[i]);                    //to print result
}
}

I was thinking to use struct but i have no clue for starting it. i'm a beginenr in C, and sorry for my bad style. Thank you in prior.

Upvotes: 2

Views: 29638

Answers (2)

Lundin
Lundin

Reputation: 213882

The LSB is given simply by masking is out with a bit mask: input[i] & 0xFF.

The code you have posted input[i] >> 8 gives the next byte before that. However, it also gives anything that happened to be stored in the most significant bytes, in case int is 32 bits. So again you need to mask, (input[i] >> 8) & 0xFF.

Also avoid bit-shifting on signed types such as int, because if they have negative values, you invoke poorly-specified behavior which leads to bugs.

The correct way to mask out the individual bytes of an int is this:

// 16 bit system  
uint8_t bytes [sizeof(int)] = 
{
  ((uint16_t)i >> 0) & 0xFF,  // shift by 0 not needed, of course, just stylistic
  ((uint16_t)i >> 8) & 0xFF,
};

// 32 bit system  
uint8_t bytes [sizeof(int)] = 
{
  ((uint32_t)i >>  0) & 0xFF,
  ((uint32_t)i >>  8) & 0xFF,
  ((uint32_t)i >> 16) & 0xFF,
  ((uint32_t)i >> 24) & 0xFF,
};

This places the LSB at index 0 in this array, similar to Little Endian representation in memory. Note however that the actual bit-shift is endianess-independent, and also fast, which is why it's a superior method.

Solutions based on unions or pointer arithmetic depend on endianess and are often buggy (pointer aliasing violations), so they should be avoided, as there is no benefit of using them.

Upvotes: 11

Waqas Shabbir
Waqas Shabbir

Reputation: 753

you can use the bit-masking concept.
Like this,

uint16_t val = 0xABCD;
uint8_t vr  = (uint8_t) (val & 0x00FF);

Or this can also be done by simply explicit type casting, as an 8-bit integer only carries LBS 8-bits from 16-bits value, & discards the remaining MSB 8-bits (by default, when assigns a larger value). This all done after shifting of bits.

Upvotes: 2

Related Questions