Qual é a saída deste programa e o que ele retorna ao sistema operacional?

StackOverflow https://stackoverflow.com/questions/279837

  •  07-07-2019
  •  | 
  •  

Pergunta

É uma espécie de quebra -cabeça C. Você deve saber se o programa concluir sua execução; se sim, quanto tempo leva para executar e o que ele retorna ao sistema operacional.

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;
}

Editar] Eu removi a etiqueta das perguntas da entrevista, pois essa parece ser a principal coisa que as pessoas estão se opondo. Este é um ótimo quebra -cabeça, mas como todos já apontaram, não é uma ótima pergunta de entrevista.

Foi útil?

Solução

Apesar do fato de que esta é uma questão de entrevista horrível, é realmente bastante interessante:

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

Essencialmente, este é um contador Base-256 (assumindo bytes de 8 bits) com 256 dígitos, o programa sairá quando o contador inteiro "rsões over".

A razão pela qual isso é interessante é porque o código é realmente completamente legal (nenhum comportamento indefinido ou de implementação definido que você geralmente encontra nesses tipos de perguntas) e na verdade existe um problema legítimo de algoritmo, embora um pouco escondido, na mistura. A razão pela qual é uma questão de entrevista horrível é porque eu não esperaria que alguém se lembrasse da precedência e associatividade dos operadores envolvidos na declaração do tempo. Mas faz um pequeno exercício divertido e perspicaz.

Outras dicas

Este código é lixo, veja comentários

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
}

Pode terminar, pode não; O loop do tempo está essencialmente examinando um buffer não inicializado, para que possa dar uma violação de acesso; Não me lembro da precedência de ligação de ++*p ++, nem me importo o suficiente para procurar

Se essa é realmente uma pergunta de entrevista, minha resposta é "Se esse é o tipo de código com o qual você espera que eu trabalhe, não quero o trabalho"

EDIT: Graças a Robert Gamble por me lembrar que as matrizes estáticas são automaticamente inicializadas para zero, então o código não é um lixo completo - mas eu ainda não gostaria de mantê -lo ou trabalhar com o Nutjob que o escreveu ;-)

A resposta certa a esta pergunta é:

Este código é incontrolável, não testável, não serve para não ter um propósito e deve ser removido ou reescrito.

Qualquer outra coisa significa que o entrevistado não está pensando como engenheiro de software.

Mais uma vez, você pode não estar entrevistando para a posição de engenharia.

unsigned char *p, *q;

Isso não está desgastado em muitos níveis? Primeiro de tudo, existe um char não assinado? Segundo, e eu posso estar errado aqui, então não me cite, mas não char *P, Q produz resultados descolados? É isso, ou facilita fazer char P, Q, que seria uma forma ruim.

O seguinte é muito melhor:

char* p;
char* q;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top