For example :
f(8)=8 f(9)=8
Can I do x = x/2*2;
? Is there a risk that the compiler will optimize away such expression ?
The signed integer is represented in twos complement notation. The most significant byte is 0 and the least significant is 3. The unsigned integer is represented by an unsigned binary number whose most significant byte is 0; the least significant is 3. See the Signed Integer and Unsigned Integer figure (Figure 1).
A 1-byte unsigned integer has a range of 0 to 255. Compare this to the 1-byte signed integer range of -128 to 127. Both can store 256 different values, but signed integers use half of their range for negative numbers, whereas unsigned integers can store positive numbers that are twice as large.
Unsigned Integers (often called "uints") are just like integers (whole numbers) but have the property that they don't have a + or - sign associated with them. Thus they are always non-negative (zero or positive).
Subtracting two unsigned values of the same size will result in an unsigned value. If the first operand is less than the second the result will be arithmetically in correct.
The compiler is allowed to make any optimisiations it likes so long as it does not introduce any side effects into the program. In your case it can't cancel the '2's as then the expression will have a different value for odd numbers.
x / 2 * 2
is evaluated strictly as (x / 2) * 2
, and x / 2
is performed in integer arithmetic if x
is an integral type.
This, in fact, is an idiomatic rounding technique.
Since you specified the integers are unsigned, you can do it with a simple mask:
x & (~1u)
Which will set the LSB to zero, thus producing the immediate even number that is no larger than x
. That is, if x
has a type that is no wider than an unsigned int
.
You can of course force the 1
to be of the same type as a wider x
, like this:
x & ~((x & 1u) | 1u)
But at this point, you really ought to look at this approach as an exercise in obfuscation, and accept Bathsheba's answer.
I of course forgot about the standard library. If you include stdint.h
(or cstdint
, as you should in C++ code). You can let the implementation take care of the details:
uintmax_t const lsb = 1; x & ~lsb;
or
x & ~UINTMAX_C(1)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With