1

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.

3 Answers3

1

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)))
0___________
  • 60,014
  • 4
  • 34
  • 74
0

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.

deamentiaemundi
  • 5,502
  • 2
  • 12
  • 20
0

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!

Alain Merigot
  • 10,667
  • 3
  • 18
  • 31
  • I like your logic and your answer is very clear and concise, but how would I go about this without using the `-` operator? Also, I am only allowed to use 8 operators. –  Jan 31 '19 at 03:57
  • I missed the fact that "-" was fordidden. But the only operation required is "-1" and it can be replaced by +(~0). Concerning the number of operators, it fits, but not with a oneliner. I update the answer. – Alain Merigot Jan 31 '19 at 06:56
  • @vastImmortalSuns There was a bug in previous answer, but I found a much simpler way that fully respects the constraints. – Alain Merigot Jan 31 '19 at 12:31
  • Ah I see! Thanks for clearing that up, I didn't realize that you could even negate 0, but now that makes perfect sense :) –  Jan 31 '19 at 19:44