Reputation: 555
I am trying to set the most significant bit in a long long unsigned, x. To do that I am using this line of code:
x |= 1<<((sizeof(x)*8)-1);
I thought this should work, because sizeof gives size in bytes, so I multiplied by 8 and subtract one to set the final bit. Whenever I do that, the compiler has this warning: "warning: left shift count >= width of type"
I don't understand why this error is occurring.
Upvotes: 13
Views: 15484
Reputation: 11
Thanks to the 2's complement representation of negative integers, the most-negative interger is exactly the desired bit pattern with only the MSB set. So x |= (unsigned long long )LONG_LONG_MIN;
should work too.
Upvotes: 0
Reputation: 320481
The 1
that you are shifting is a constant of type int
, which means that you are shifting an int
value by sizeof(unsigned long long) * 8) - 1
bits. This shift can easily be more than the width of int
, which is apparently what happened in your case.
If you want to obtain some bit-mask mask of unsigned long long
type, you should start with an initial bit-mask of unsigned long long
type, not of int
type.
1ull << (sizeof(x) * CHAR_BIT) - 1
An arguably better way to build the same mask would be
~(-1ull >> 1)
or
~(~0ull >> 1)
Upvotes: 20
Reputation: 7257
use 1ULL << instead of 1 <<
Using just "1" makes you shift an integer. 1ULL will be an unsigned long long which is what you need.
An integer will probably be 32 bits and long long
probably 64 bits wide. So shifting:
1 << ((sizeof(long long)*8)-1)
will be (most probably):
1 << 63
Since 1 is an integer which is (most probably) 32 bits you get a warning because you are trying to shift past the MSB of a 32 bit value.
Upvotes: 7
Reputation: 42139
The literal 1
you are shifting is not automatically an unsigned long long
(but an int
) and thus does not have as many bits as you need. Suffix it with ULL
(i.e., 1ULL
), or cast it to unsigned long long
before shifting to make it the correct type.
Also, to be a bit safer for strange platforms, replace 8
with CHAR_BIT
. Note that this is still not necessarily the best way to set the most significant bit, see, e.g., this question for alternatives.
You should also consider using a type such as uint64_t
if you're assuming unsigned long long
to be a certain width, or uint_fast64_t
/uint_least64_t
if you need at least a certain width, or uintmax_t
if you need the largest available type.
Upvotes: 1