Question

It's kind of a C puzzle. You have to tell if the program finish its execution, if so, how much time it takes to run and what it returns to the OS.

static unsigned char buffer[256];

int main(void)
{
  unsigned char *p, *q;
  q = (p = buffer) + sizeof(buffer);
  while (q - p)
  {     
      p = buffer;
      while (!++*p++);
  }
  return p - q;
}

[EDIT] I removed the interview-questions tag since that seems to be the primary thing people are objecting to. This is a great little puzzle but as everyone has already pointed out, not a great interview question.

Was it helpful?

Solution

Despite the fact that this is a horrible interview question, it is actually quite interesting:

static unsigned char buffer[256];

int main(void)
{
  unsigned char *p, *q;
  q = (p = buffer) + sizeof(buffer);
  /* This statement will set p to point to the beginning of buffer and will
     set q to point to one past the last element of buffer (this is legal) */
  while (q - p)
  /* q - p will start out being 256 and will decrease at an inversely 
     exponential rate: */
  {     
      p = buffer;
      while (!++*p++);
      /* This is where the interesting part comes in; the prefix increment,
         dereference, and logical negation operators all have the same
         precedence and are evaluated **right-to-left**.  The postfix
         operator has a higher precedence.  *p starts out at zero, is
         incremented to 1 by the prefix, and is negated by !.
         p is incremented by the postfix operator, the condition
         evaluates to false and the loop terminates with buffer[0] = 1.

         p is then set to point to buffer[0] again and the loop continues 
         until buffer[0] = 255.  This time, the loop succeeds when *p is
         incremented, becomes 0 and is negated.  This causes the loop to
         run again immediately after p is incremented to point to buffer[1],
         which is increased to 1.  The value 1 is of course negated,
         p is incremented which doesn't matter because the loop terminates
         and p is reset to point to buffer[0] again.

         This process will continue to increment buffer[0] every time,
         increasing buffer[1] every 256 runs.  After 256*255 runs,
         buffer[0] and buffer[1] will both be 255, the loop will succeed
         *twice* and buffer[2] will be incremented once, etc.

         The loop will terminate after about 256^256 runs when all the values
         in the buffer array are 255 allowing p to be incremented to the end
         of the array.  This will happen sometime after the universe ends,
         maybe a little sooner on the new Intels ;)
      */
  }
  return p - q;
  /* Returns 0 as p == q now */
}

Essentially this is a base-256 (assuming 8-bit bytes) counter with 256 digits, the program will exit when the entire counter "rolls over".

The reason this is interesting is because the code is actually completely legal C (no undefined or implementation defined behavior that you usually find in these types of questions) and there is actually a legitimate algorithm problem, albeit a little hidden, in the mix. The reason it is a horrible interview question is because I wouldn't expect anyone to remember the precedence and associativity of the operators involved in the while statement. But it does make for a fun and insightful little exercise.

OTHER TIPS

this code is garbage, see comments

static unsigned char buffer[256];
int main(void)
{
  unsigned char *p, *q;
  q = (p = buffer) + sizeof(buffer);    //p=buffer, q=buffer+256
  while (q - p)    //q-p = 256 on first iteration
  {     
      p = buffer;        //p=buffer again
      while (!++*p++);   //increment the value pointed at by p+1 and check for !0
  }
  return p - q;    //will return zero if loop ever terminates
}

it might terminate, it might not; the while loop is essentially scanning an uninitialized buffer so it might throw an access violation instead; i don't remember the binding precedence of ++*p++, nor do i care enough to look it up

if this is really an interview question, my answer is "if this is the kind of code you expect me to work with, i don't want the job"

EDIT: thanks to Robert Gamble for reminding me that static arrays are automatically initialized to zero, so the code is not complete garbage - but I still would not want to maintain it or work with the nutjob that wrote it ;-)

The right answer to this question is:

This code is unmaintainable, untestable, serves no purpose and should be removed or rewritten.

Anything else means that the interviewee is not thinking as a software engineer.

Than again, you might be not be interviewing for engineering position.

unsigned char *p, *q;

Isn't this worng on many levels? First of all, is there such a thing as an unsigned char? Second, and I may be wrong here, so don't quote me, but doesn't char *p, q produce funky results? It's either that, or it makes it easy to do char p, q, which would be bad form.

The following is much better:

char* p;
char* q;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top