Каков вывод этой программы и что она возвращает в ОС? - PullRequest
2 голосов
/ 11 ноября 2008

Это своего рода загадка С. Вы должны указать, завершит ли программа свое выполнение, если это так, сколько времени потребуется для запуска и что она возвращает в ОС.

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] Я удалил тег интервью-вопросов, так как это, кажется, является основной вещью, против которой возражают люди. Это отличная маленькая головоломка, но, как все уже отметили, это не очень хороший вопрос для интервью.

Ответы [ 4 ]

13 голосов
/ 11 ноября 2008

Несмотря на то, что это ужасный вопрос для интервью, на самом деле он довольно интересен:

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 */
}

По сути, это счетчик base-256 (при условии 8-битных байтов) с 256 цифрами, программа закроется, когда весь счетчик "перевернется".

Причина, по которой это интересно, заключается в том, что код на самом деле является полностью допустимым C (нет неопределенного или определенного реализацией поведения, которое вы обычно обнаруживаете в таких типах вопросов), и на самом деле существует законная проблема алгоритма, хотя и немного скрытая перемешать. Причина, по которой это ужасный вопрос для интервью, заключается в том, что я не ожидал, что кто-нибудь вспомнит приоритет и ассоциативность операторов, участвующих в операторе while. Но это делает для забавного и проницательного маленького упражнения.

12 голосов
/ 11 ноября 2008

этот код является мусором, см. Комментарии

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
}

это может закончиться, это может не произойти; цикл while по сути сканирует неинициализированный буфер, поэтому вместо этого он может выдавать нарушение прав доступа; я не помню приоритет связывания ++ * p ++, и при этом я не забочусь достаточно, чтобы посмотреть его

если это действительно вопрос для собеседования, мой ответ: «если это тот код, с которым вы ожидаете, что я буду работать, я не хочу работать»

РЕДАКТИРОВАТЬ: спасибо Роберту Гэмблу за напоминание о том, что статические массивы автоматически инициализируются нулем, поэтому код не является полным мусором - но я все равно не хотел бы поддерживать его или работать с чокнутым, который написал это; 1008 *

4 голосов
/ 11 ноября 2008

Правильный ответ на этот вопрос:

Этот код не поддерживается, не проверяется, не имеет смысла и должен быть удален или переписан.

Все остальное означает, что собеседник не думает как инженер-программист.

Снова, возможно, вы не проходите собеседование на должность инженера.

0 голосов
/ 11 ноября 2008
unsigned char *p, *q;

Разве это не работа на многих уровнях? Прежде всего, существует ли такая вещь как неподписанный символ? Во-вторых, и я могу ошибаться здесь, так что не цитируйте меня, но разве char * p, q не дает странных результатов? Это либо так, либо позволяет легко использовать char p, q, что было бы плохо.

следующее намного лучше:

char* p;
char* q;
...