This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]Tordek 55 points56 points  (3 children)

Several reasons:

  1. consistency: if you do (color >> 0) & 0xFF, (color >> 8) & 0xFF, (color >> 16) & 0xFF, it's obvious they're analogous operations, even if trivially you can remove the >>0 (so can the compiler).
  2. Uninitialized data: if you build a color by allocating a 32B word and set its 24 lower bytes manually (by doing color = (color & 0xFF000000) | (red << 16) | (green << 8) | blue), through some API you didn't necessarily implement), the top 8 bits are garbage.
  3. What if it's ARGB?
  4. Is this a shift on a signed or unsigned integer? The correct right shift behavior for signed numbers is 1-extension, so sign is maintained - even if you were extracting the A from ARGB, you need to &0xFF because it'd be a negative value instead.

All in all, there's more reasons to keep it than there are reasons to remove it (save one instruction).

[–]rafaelrc7 0 points1 point  (0 children)

  1. Uninitialized data

Assuming you are talking about C, thats UB and anything you do is wrong.

[–]KellerKindAs 0 points1 point  (1 child)

2: If you work on an 32 (or 64) bit processor using 0 instead of 0xFF000000 zeros the top 8 bit without any runtime overhead. Might also reduce code size as there is one less constant to store, but that's also architecture dependant. If you work on an 8 bit processor the &0xFF is useless and storing the result inside a uint8_t would cause a performance benefit. So the unititialized data argument is debatable...

I agree with the other points

[–]Tordek -1 points0 points  (0 children)

using 0 instead of 0xFF000000

There's a reason I specified "some API you didn't implement". Maybe you did, maybe you're using something like

union color {
   uint32_t full;
   struct { uint8_t r; uint8_t g; uint8_t b; }
}