Reputation:
I'm working with bitwise and logical operators in C. I'm familiar with concept and purpose of these operators, but have run into bit of a problem.
I need to determine whether an integer x
can fit into a short. I am restricted to using the operators ! ~ & ^ | + << >>
. Also, I can only use up to 8 of these operators.
I know from several other posts (like this one: How to tell if a 32 bit int can fit in a 16 bit short) that a solution like
!(((((x) & 0xffff8000) >> 15) + 1) & 0x1fffe)
would work just fine (credit to Emil Romanus). However, I'm also forbidden to use any constants that are not 0x0
and 0xff
.
I'm mostly confused on the logic here. Any ideas?
EDIT: I forgot to mention conditional statement are also forbidden. So no ifs, elses, loops etc.
Upvotes: 1
Views: 2085
Reputation: 11537
Solution is based on the fact that x^(x<<1)
will have its 16 MSB at zero iff the 17 MSB of x
are all equal and x
can be coded on 16 bits.
Hence
return (x^(x<<1))&(0xffff0000)==0;
solves the problem.
For readability, operations are split in several instructions and to reduce the number of used operators the final test is reversed (it does not seem to be forbidden).
int canNOTbemappedto16bits(int x) {
int one = !0x0; // 1 op
int ffff = (unsigned short) ~0x0;//1 op
int ffff0000 = (unsigned int) ~0x0 ^ ffff; // 2ops
return (x^(x<<one))&ffff0000 ; // 3ops
}
7 ops!
Upvotes: 0
Reputation: 5525
For readability set invuint = ~0u
and invushort = ~((short)0u)
, than we can do invuint - invushort
which is either 0
or not. 0
in standard C is equal to false
, so you can see with a simple !(invuint - invushort)
if an unsigned int
fits into an unsigned short
.
But that is most likely not what you are asked to do, it would be a bit too easy. If you need to know if the content of an unsigned int
fits into an unsigned short
it gets a bit more complicated.
We can reuse the incushort = ~((short)0u)
here as a mask.
With an_uint = 0; an_uint = incushort
we set the lowest bits of an_uint
to ones so we have 0x0000ffff
. Reversing that with ~an_uint
gets you 0xXXXX0000
where the X
stand for an unknown number of ones. So if sizeof(unsigned int) == sizeof(unsigned short)
we get a 0
but we could have gotten that simpler, see above.
If we use mask = 0xXXXX0000
as a mask to get all of the bits that are larger than an unsigned short
with uint_with_unknown_content & mask
we get a 0
if uint_with_unknown_content
fits into an unsigned short
.
Upvotes: 0
Reputation: 67546
that is your sollution
(unsigned)~0 == 0xffff
or without ==
!((unsigned)~0 - 0xffff)
!((unsigned)~0 ^ 0xffff)
or if only 0xff is allowed
!((unsigned)~0 ^ (((0xff << (!!0xff << !!0xff << !!0xff << !!0xff))) | 0xff)))
Upvotes: 1