¿Cuál es el resultado de este programa y qué devuelve al sistema operativo?

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

  •  07-07-2019
  •  | 
  •  

Pregunta

Es una especie de rompecabezas de C. Debe decir si el programa finaliza su ejecución, en caso afirmativo, cuánto tiempo tarda en ejecutarse y qué devuelve al sistema operativo.

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] Eliminé la etiqueta de preguntas de la entrevista, ya que parece ser lo principal a lo que las personas se oponen. Este es un pequeño gran rompecabezas, pero como todos ya han señalado, no es una gran pregunta para la entrevista.

¿Fue útil?

Solución

A pesar de que esta es una pregunta de entrevista horrible, en realidad es bastante interesante:

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

Esencialmente, se trata de un contador de base 256 (suponiendo bytes de 8 bits) con 256 dígitos, el programa se cerrará cuando todo el contador "pase".

La razón por la que esto es interesante es porque el código es en realidad completamente legal C (no hay un comportamiento indefinido o definido por la implementación que generalmente se encuentra en este tipo de preguntas) y en realidad hay un problema de algoritmo legítimo, aunque un poco oculto, en el mezcla. La razón por la que es una pregunta de entrevista horrible es porque no esperaría que nadie recordara la precedencia y la asociatividad de los operadores involucrados en la declaración while. Pero sí lo convierte en un pequeño ejercicio divertido y perspicaz.

Otros consejos

este código es basura, ver comentarios

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
}

puede terminar, puede que no; el ciclo while esencialmente está escaneando un búfer no inicializado, por lo que podría arrojar una infracción de acceso; No recuerdo la precedencia vinculante de ++ * p ++, ni me importa lo suficiente como para buscarlo

si esta es realmente una pregunta de entrevista, mi respuesta es "si este es el tipo de código con el que espera que trabaje, no quiero el trabajo"

EDITAR: gracias a Robert Gamble por recordarme que las matrices estáticas se inicializan automáticamente a cero, por lo que el código no es basura completa, pero aún así no quisiera mantenerlo o trabajar con el loco que lo escribió; -)

La respuesta correcta a esta pregunta es:

  

Este código no se puede mantener, no se puede probar, no sirve para nada y debe eliminarse o reescribirse.

Cualquier otra cosa significa que el entrevistado no está pensando como ingeniero de software.

De nuevo, es posible que no estés siendo entrevistado para un puesto de ingeniero.

unsigned char *p, *q;

¿No es este trabajo en muchos niveles? En primer lugar, ¿existe algo así como un personaje sin firmar? Segundo, y puedo estar equivocado aquí, así que no me cites, pero ¿char * p, q no produce resultados funky? Es eso, o hace que sea fácil hacer char p, q, que sería una mala forma.

Lo siguiente es mucho mejor:

char* p;
char* q;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top