On 9/17/18 4:05 PM, Eric Blake wrote:
Also, ~((n)-1) is identical to -(n), if you want less typing (well, as
long as you assume twos-complements signed numbers, but that's pretty
safe to assume these days).
Nir is correct that the C standard states that ~, &, and | on signed
values have implementation-defined behavior (it is only undefined once
you move over to << and >>). If you are computing & or | where both
values are positive, the results are well-defined. But if either
operand is negative, you can get odd results. Similarly, ~ is always
implementation-defined on signed (it is well-defined to flip all bits,
but unless you know if the implementation defined ints as
sign-magnitude, ones-complement, or twos-complement, you can end up with
a different result than intended. If you don't want to assume
twos-complement, then you could write it as:
~((n)-1U)
to force coercion to unsigned for most inputs, at which point ~ is
well-defined. Except that (int64_t - 1U) doesn't coerce to unsigned.
And you don't want to blindly write 1ULL to force 64-bit math
everywhere, when the macro is otherwise fine on 32-bit inputs.
You can use the fact that '1 ? a : b' produces the expression 'a'
coerced to the wider type of either 'a' or 'b'. And there's gcc's
typeof operator, since you're already relying on extensions.
(Note, I'm trying to give you enough hints to be able to write a working
patch, without submitting it myself, because I'm worried that I'm
perhaps tainted license-wise on this particular issue since I patched a
similar bug in qemu where the license does not permit wholesale copying
over to nbdkit)
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization:
qemu.org |
libvirt.org