2

This is not important and should be quite simple, I just don't understand what I'm doing wrong. The story behind this is that I'm playing with tinyNeoPixel lib on the attiny85, and I'm trying to dive a bit deeper than I need.

This is traditional ANSI C and I'm using a Raspberry Pi3 for this test, but for this case this should be irrelevant. The sizeof(c) on the printf just shows that 'c' is 4 bytes, as expected.

I'm trying to extract the Red, Green, and Blue part of a color that's stored as a 32 bits number

Obviously I'm failing to return the result as a 1 byte value, can same one please tell me how do I do that ? Just casting to (uint8_t) just produces zero.

Thank you.

pi3:~/src$ cat a.c
#include <stdio.h>

typedef unsigned char uint8_t;
typedef unsigned long int uint32_t;

#define Red(x)   (x & 0xff000000)
#define Green(x) (x & 0x00ff0000)
#define Blue(x)  (x & 0x0000ff00)

void main()
{
    uint32_t c;
    uint8_t r,g,b;

    c=0xffeecc00;
    r=Red(c);
    g=Green(c);
    b=Blue(c);

    printf("%d - %08x - %02x %02x %02x\n", sizeof(c), c, r, g, b);
    printf("%d - %08x - %02x %02x %02x\n", sizeof(c), c, Red(c), Green(c), Blue(c));
}


pi3:~/src$ gcc a.c -o a
pi3:~/src$ ./a
4 - ffeecc00 - 00 00 00
4 - ffeecc00 - ff000000 ee0000 cc00

The solution is:

#define Red(x) (((x) & 0xff000000) >> 24)
#define Green(x) (((x) & 0x00ff0000) >> 16)
#define Blue(x) (((x) & 0x0000ff00) >> 8)

With this macros this produces

pi3:~/src$ ./a
4 - ffeecc00 - ff ee cc
4 - ffeecc00 - ff ee cc

as it should. Thank you guys.

ocsav
  • 23
  • 3
  • 5
    Looks like you probably need to shift as well as mask. That is, try something like `#define Red(x) (((x) & 0xff000000) >> 24)` – Steve Summit Nov 16 '19 at 22:31
  • That's it..shifting 24 bits for Red, 16 for Green and 8 for blue solved it, now each macro returns a 8 bit value. Thank you. – ocsav Nov 16 '19 at 22:40
  • @SteveSummit - you should make this an answer. OP - welcome to SO. When Steve makes this an answer, you should accept it (or another one if it fits you better). – ysap Nov 16 '19 at 23:43
  • you''re getting UB. `sizeof` returns a `size_t` which [must be printed out using `%zu` and not `%x`](https://stackoverflow.com/q/940087/995714) – phuclv Nov 17 '19 at 03:48
  • @phuclv, the sizeof is being printed with %d not %x, being an unsigned it should be printed with %u. I'm not exactly sure what the z does there. – ocsav Nov 17 '19 at 11:43
  • @ocsav whatever, both `%d` and `%x` are wrong and [invokes UB for the wrong format specifer](https://stackoverflow.com/q/16864552/995714). For example on some 64-bit architecture size_t is 64-bit long and you'll mess up the stack by popping only 32 bits. `%zu` will do the correct thing. Did you even read the linked question? – phuclv Nov 17 '19 at 12:34
  • @phuclv, don't stress out, you're right of course. In fact I red the linked question but as I was getting the value that I expected (4) I did not thought it was relevant. I learned C by K&R v2, at that time there was no %zu, and I use C when I don't have other choice, so I don't know much. Thank you for your help. – ocsav Nov 17 '19 at 13:09

1 Answers1

2

You need to shift as well as mask. That is, try something like

#define Red(x) (((x) & 0xff000000) >> 24)

and similarly for your Green() and Blue() macros.

(Also note that I've added two extra pairs of parentheses to the macro definition, for safety in expansion.)

Steve Summit
  • 45,437
  • 7
  • 70
  • 103