4 ms·
Believe it or not, this makes the behavior more like what you'd expect in many cases. For example: uint8_t x = 4; extern volatile uint64_t *reg; *reg &=
by veltas 4y ago
Believe it or not, this makes the behavior more like what you'd expect in many cases. For example:
uint8_t x = 4;
extern volatile uint64_t *reg;
*reg &= ~x;
In the last statement x is promoted to an int, and then when the logical NOT occurs every bit is set to 1, including the high bit. When it's converted to a uint64_t for the AND, the high bits are also set to 1. So the result is that the final statement clears only bit 2 in *reg.
If it promoted to unsigned int, then it would also clear bits 32-63.
- codeflo 4y agoI don’t find that very convincing. It’s simply ambiguous, I might want this: *reg &= ~(uint64_t)x; or, and there’s no elegant way to even write this in C, I might want: *reg &=(uint64_t)(uint8_t)~x; The fact that I have to write two casts here to undo the damage of the auto-promotion is evidence of how broken this is.
- veltas 4y agoThat second line can be written: *reg &= (uint8_t)~x; Or: *reg &= ~x & 0xFF;
- tialaramex 4y agoextern volatile uint64_t *reg; *reg &= ~x; People should stop doing this. What this means is: extern volatile uint64_t *reg; uint64_t tmp = *reg; tmp &= ~x; *reg = temp; But of course when you write that chances are somebody will point out that you're running in interruptible context sometimes in this function, so that's actually introducing a race condition. Why didn't they say so when you wrote it your way? Because that looked like a single operation and so it wasn't obvious it might get interrupted.