3

In c, I know an unsigned char is of size 1 byte (= 1 octet = 8 bits), and I know that an unsigned char is in fact a integer value between 0 and 255, now that if I have the following unsigned char variable:

unsigned char c = 255; //(this value can be any value from 0 to 255)


How could I get a table of 8 elements indicating every bit value (0 or 1) of this variable? (something like this : {1, 1, 1, 1, 1, 1, 1, 1}) Is there any easy way to do this in c?

Vertexwahn
  • 7,709
  • 6
  • 64
  • 90
SWIIWII
  • 387
  • 5
  • 15

2 Answers2

6

A common approach to extracting bits in C is using bit shift operation:

int bits[8];
for (int i = 0 ; i != 8 ; i++) {
    bits[i] = (c & (1 << i)) != 0;
}

1 << i produces binary numbers with 1 set in i-th position, i.e. 12, 102, 1002, 10002, and so on.

Operator & uses 1 << i as a "mask", selecting a single bit of c marked by 1 in the value of the mask. Comparison != 0 completes the job, producing zero or one depending on the value of the bit.

Another approach is shifting c to the right, and masking with 1, like this:

int bits[8];
for (int i = 0 ; i != 8 ; i++) {
    bits[i] = (c >> i) & 1;
}

This is similar to the first approach, but the masking is done in the least significant bit position.

Note: On computers with CHAR_BIT set to a number other than 8 this would extract only the lower 8 bits.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • This will fail on some TI chips, for example, where a byte isn't 8 bits. – Cloud May 27 '16 at 15:59
  • @SWIIWII It is correct, it's just written out LSB first ("backwards"). 83 in binary is 0b1010011, so if you want your MSB to be first, use `bits[7-i]` instead of `bits[i]` in the assignment. – Sergey Kalinichenko May 27 '16 at 16:01
  • @dasblinkenlight I disagree. TC/OP just states (incorrectly) that a byte = 8 bits, not that on his/her specific platform this is the specific case. – Cloud May 27 '16 at 16:03
  • 1
    @dasblinkenlight Yeah, that worked, the **7-i** helped me get the reverse order (the right order). – SWIIWII May 27 '16 at 16:13
  • 1
    @DevNull On chips where a byte isn't 8 bits this would extract the lowest 8 bits. The standard says that `CHAR_BIT` must not be less than 8, so this approach would not fail as in "produce UB", but it would fail to extract bits above 8-th. – Sergey Kalinichenko May 27 '16 at 16:15
1

beside bitwise operations (which are better and I'd say standard way to do this), you can use unions to access single bits:

typedef union {
    unsigned char c;
    struct {
        unsigned char b0 :1;
        unsigned char b1 :1;
        unsigned char b2 :1;
        unsigned char b3 :1;
        unsigned char b4 :1;
        unsigned char b5 :1;
        unsigned char b6 :1;
        unsigned char b7 :1;
    };
} byte_struct;

int main(int argc, char** argv) {
    byte_struct c;
    c.c = 0xaa;

    printf("%u\n", c.b7);
    printf("%u\n", c.b6);
    printf("%u\n", c.b5);
    printf("%u\n", c.b4);
    printf("%u\n", c.b3);
    printf("%u\n", c.b2);
    printf("%u\n", c.b1);
    printf("%u\n", c.b0);

    return (EXIT_SUCCESS);
}

note: order of single bit variables is implementation defined, so you should be careful with them and use compiler-specific flags to force order

Iłya Bursov
  • 23,342
  • 4
  • 33
  • 57
  • 5
    Do not do this: *The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined* In english: bit-field member `b0` might not represent the least significant bit. – 2501 May 27 '16 at 15:54
  • 2
    @2501 yes, it is implementation defined, but it does not mean that you cannot use it, you can control it via compiler flags and thus depend on it, of course your can also shoot your leg – Iłya Bursov May 27 '16 at 16:02