c - لماذا ينتج هذا البرنامج إخراجًا فرديًا عندما يكون المتغير غير مهيأ؟




loops scope (4)

أعتقد أن هذا ما يحدث:

Breakpoint 1, main () at abc.c:4
4       int j = 0;
(gdb) s
5       int i = 0;
(gdb)
6       for(j=0;j<5;j++){
(gdb) p &i
$23 = (int *) 0x7fff5fbffc04           //(1) (addr = 0x7fff5fbffc04) i = 0
(gdb) p i
$24 = 0                                              // (2) i == 0
(gdb) s
7           printf("Iteration %d :  %d ",j+1,i);
(gdb) p &i
$25 = (int *) 0x7fff5fbffc00            //(3) here compiler finds there is contention in variable 'i' and assigns the inner one which is in present scope. Now, when subroutines are called, the stack frame is populated with (arguments, return address and local variables) and this is when the inner 'i' was also got allocated in this inner loop block but not initialized yet and this is the reason i get garbage value in the first integration output.

(gdb) p i
$26 = 1606417440                          // (4)  Here i == 1606417440 (Garbage)
(gdb) s
9           printf("%d",i);
(gdb) s
10          i = 5;
(gdb) p &i
$27 = (int *) 0x7fff5fbffc00
(gdb) p i
$28 = 1606417440
(gdb) s
11          printf("\n");
(gdb) p &i
$29 = (int *) 0x7fff5fbffc00
(gdb) p i                                                //(5) after executing previous statement, now i == 5
$30 = 5
(gdb) 
int main() {
    int j = 0;
    int i = 0;
    for (j = 0; j < 5; j++) {
        printf("Iteration %d :  %d ", j + 1, i);
        int i;
        printf("%d", i);
        i = 5;
        printf("\n");
    }
}

ينشئ رمز أعلاه الإخراج التالي:

Iteration 1 :  0 0
Iteration 2 :  0 5
Iteration 3 :  0 5
Iteration 4 :  0 5
Iteration 5 :  0 5

لا أستطيع أن أفهم سبب قيمة printf الثانية في التكرارات 2،3،4،5 هي 5.

أفهم لماذا القيمة الأولى هي 0 في كل التكرار هو أن نطاق i في الحلقة هو محلي ويتم تدميره بمجرد أن نذهب إلى التكرار الجديد كما أعلن في حلقة for .

ولكنني غير قادر على معرفة السبب في أن هذه القيمة تصبح 5 في printf الثاني.


إذا كنت تعلن عن متغير محلي ولا تعطيه قيمة قبل استخدامه ، إذا كان لديك سلوك غير معرف.

يقول معيار C ،

تتم تهيئة المتغيرات ذات مدة التخزين التلقائي في كل مرة يتم فيها تنفيذ بيان تعريفها. يتم إتلاف المتغيرات ذات مدة التخزين التلقائي المعلنة في الكتلة عند الخروج من الكتلة.


لدى المترجمين C بعض خطوط العرض في كيفية تنفيذهم للأشياء ، ولن يكون الأمر غير معتاد على الإطلاق بالنسبة إلى "i" المحلي ألا يتم في الواقع إعادة إنشاء كل مسار للحلقة. من المرجح أنه يتم إنشاؤه مرة واحدة فقط ، وإعادة استخدامه في كل مرة تمر. في هذه الحالة ، تكون الطباعة الأولى خارج نطاق المتغير المحلي بحيث يستخدم i من خارج الحلقة. تستخدم الطبعة الثانية i المحلي كما هو في النطاق ، وبعد ضبط التكرار الأول إلى 5. في التكرار الأول ، القيمة الصحيحة غير معرفة ، ليست 0 ، ولكن سلوك غير محدد هو تنفيذ معين ، في التنفيذ الخاص بك يبدو أنه تتم تهيئة تلقائيًا إلى 0.


printf الثاني في البرنامج الخاص بك هو طباعة قيمة garbage من المتغير المحلي غير مهيأ i . في الحالة العامة ، السلوك غير معروف.

بالصدفة ، موقع التخزين الذي يمثل i (ذاكرة الخلية أو سجل CPU) هو نفسه في كل تكرار للدورة. بحادث آخر ، يتم تنفيذ جسد دورتك كبيان مركب واحد لكل تكرار (على العكس من إلغاء الدورة وتنفيذ جميع التكرارات في نفس الوقت بطريقة متداخلة). بحادث آخر ، يحتفظ موقع تخزين i بقيمته القديمة من التكرار السابق. لذلك ، تطابق القمامة التي تقوم بطباعتها القيمة المخزنة الأخيرة من ذلك الموقع على التكرار السابق للدورة.

لهذا السبب ترى 5 في المحلية i على كل التكرار بالإضافة إلى الأول. على التكرار الأول حدث أن قيمة garbage أن تكون 0 .





shadowing