Qual è l'output di questo programma e cosa restituisce al sistema operativo?

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

  •  07-07-2019
  •  | 
  •  

Domanda

È una specie di puzzle C. Devi dire se il programma termina la sua esecuzione, in tal caso, quanto tempo ci vuole per eseguire e cosa ritorna 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;
}

[EDIT] Ho rimosso il tag delle domande per l'intervista poiché questa sembra essere la cosa principale a cui le persone si oppongono. Questo è un piccolo enigma, ma come tutti hanno già sottolineato, non una grande domanda per l'intervista.

È stato utile?

Soluzione

Nonostante si tratti di una terribile domanda di intervista, in realtà è piuttosto 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 */
}

Essenzialmente si tratta di un contatore base-256 (assumendo byte a 8 bit) con 256 cifre, il programma termina quando l'intero contatore "passa sopra".

Il motivo per cui questo è interessante è perché il codice è in realtà completamente legale C (nessun comportamento indefinito o definito dall'implementazione che di solito trovi in ??questi tipi di domande) e c'è effettivamente un problema di algoritmo legittimo, anche se un po 'nascosto, nel mescolare. Il motivo per cui è una domanda orribile per l'intervista è perché non mi aspetto che qualcuno ricordi la precedenza e l'associatività degli operatori coinvolti nella dichiarazione while. Ma rende un piccolo esercizio divertente e perspicace.

Altri suggerimenti

questo codice è spazzatura, vedi commenti

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
}

potrebbe terminare, potrebbe non; il ciclo while sta essenzialmente scansionando un buffer non inizializzato, quindi potrebbe generare una violazione di accesso; non ricordo la precedenza vincolante di ++ * p ++, né mi interessa abbastanza cercarlo

se questa è davvero una domanda di intervista, la mia risposta è " se questo è il tipo di codice con cui ti aspetti che io lavori, non voglio il lavoro "

EDIT: grazie a Robert Gamble per avermi ricordato che gli array statici vengono inizializzati automaticamente a zero, quindi il codice non è spazzatura completa - ma non vorrei ancora mantenerlo o lavorare con il nutjob che lo ha scritto; -)

La risposta giusta a questa domanda è:

  

Questo codice non è realizzabile, non testabile, non serve a nulla e deve essere rimosso o riscritto.

Qualsiasi altra cosa significa che l'intervistato non sta pensando come ingegnere del software.

Di nuovo, potresti non essere intervistato per la posizione di ingegneria.

unsigned char *p, *q;

Questo non è indossato su molti livelli? Prima di tutto, esiste qualcosa come un carattere non firmato? Secondo, e potrei sbagliarmi qui, quindi non citarmi, ma char * p, q non produce risultati stravaganti? O è quello, o rende facile fare char p, q, che sarebbe una cattiva forma.

Quanto segue è molto meglio:

char* p;
char* q;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top