ما هو إخراج هذا البرنامج ، وماذا يعود إلى نظام التشغيل؟

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

  •  07-07-2019
  •  | 
  •  

سؤال

إنه نوع من اللغز C. عليك أن تعرف ما إذا كان البرنامج ينهي تنفيذه ، وإذا كان الأمر كذلك ، فكم من الوقت يستغرق تشغيله وما يعود إليه إلى نظام التشغيل.

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

تحرير] لقد أزلت علامة أسئلة المقابلة لأن ذلك يبدو أنه الشيء الأساسي الذي يعترض عليه الناس. هذا لغز صغير رائع ، لكن كما أشار الجميع بالفعل ، وليس سؤالًا رائعًا للمقابلة.

هل كانت مفيدة؟

المحلول

على الرغم من حقيقة أن هذا سؤال مقابلة فظيع ، فهو في الواقع مثير للاهتمام:

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

في الأساس ، هذا هو عداد الأساس 256 (على افتراض بايت 8 بت) مع 256 رقمًا ، وسيخرج البرنامج عندما يكون العداد بأكمله "يتدحرج".

والسبب في ذلك هو أمر مثير للاهتمام هو أن الكود هو في الواقع قانوني تمامًا (لا يوجد سلوك محدد غير محدد أو محدد للتنفيذ الذي عادة ما تجده في هذه الأنواع من الأسئلة) وهناك في الواقع مشكلة خوارزمية مشروعة ، وإن كان مخفيًا بعض الشيء ، في المزيج. السبب في أنه سؤال مقابلة مروع هو أنني لا أتوقع أن يتذكر أي شخص الأسبقية وربط المشغلين المشاركين في البيان. لكنه يجعل التمرين المتعة والبصيرة الصغيرة.

نصائح أخرى

هذا الرمز هو القمامة ، انظر التعليقات

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
}

قد ينتهي ، قد لا ؛ تقوم الحلقة بينما تقوم الحلقة بمسح عازلة غير محسوسة بشكل أساسي بحيث قد تلقي انتهاكًا للوصول بدلاً من ذلك ؛ لا أتذكر الأسبقية الملزمة لـ ++*p ++ ، ولا أهتم بما يكفي للبحث عنها

إذا كان هذا سؤالًا مقابلة حقًا ، فإن إجابتي هي "إذا كان هذا هو نوع الكود الذي تتوقع مني أن أعمل معه ، فأنا لا أريد الوظيفة"

تحرير: بفضل Robert Gamble لتذكيرني بأن المصفوفات الثابتة يتم تهيئة تلقائيًا إلى الصفر ، وبالتالي فإن الكود ليس كاملًا - لكنني ما زلت لا أريد الحفاظ عليها أو العمل مع Nutjob التي كتبتها ؛-)

الإجابة الصحيحة على هذا السؤال هي:

هذا الرمز لا يمكن صيانته ، غير قابل للاختبار ، لا يخدم أي غرض ويجب إزالته أو إعادة كتابته.

أي شيء آخر يعني أن الشخص الذي تمت مقابلته لا يفكر كمهندس برمجيات.

من مرة أخرى ، قد لا تجري مقابلة مع الوضع الهندسي.

unsigned char *p, *q;

أليس هذا يرتديها على العديد من المستويات؟ بادئ ذي بدء ، هل هناك شيء مثل شار غير موقعة؟ ثانياً ، وقد أكون مخطئًا هنا ، لذا لا تقتبس مني ، لكن لا تشارك *P ، س أنتج نتائج غير تقليدية؟ إما ذلك ، أو يجعل من السهل القيام بالشهر P ، س ، والتي ستكون شكل سيء.

ما يلي أفضل بكثير:

char* p;
char* q;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top