سؤال

هذا الرمز ، عند تجميعه في XLC 8.0 (على AIX 5.3) ، ينتج النتيجة الخاطئة. يجب أن تطبع 12345, ، ولكن بدلاً من ذلك يطبع 804399880. إزالة const فى مواجهة result يجعل الرمز يعمل بشكل صحيح.

أين الخطأ؟

#include <stdio.h>
#include <stdlib.h>
#include <string>

long int foo(std::string input)
{
        return strtol(input.c_str(), NULL, 0);
}

void bar()
{
        const long int result = foo("12345");
        printf("%u\n", result);
}

int
main()
{
        bar();
        return 0;
}

أمر التجميع:

/usr/vacpp/bin/xlC example.cpp -g

تحرير: تغيير سلسلة تنسيق printf أعلاه إلى "٪ ld n" لا يساعد. تحرير 2: كان إصدار AIX المستخدم 5.3 ، وليس 6.1.

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

المحلول

XLC 10.0 يعمل بشكل جيد ، ويبدو أنه خطأ في المترجم

نصائح أخرى

يتم وضع علامة على C ++ ، فماذا يحدث عند استخدام Cout بدلاً من PrintF؟

يبدو أن المشكلة هي أنك تخبر PrintF بطباعة int غير موقعة ومن ثم إرسالها طويلًا موقّعًا للطباعة بالفعل. على الأرجح أن تخطيط الذاكرة مختلف ولا يمكن للطباعة فهم ما تريد فعله بالفعل.

سيكون الأمر قليلاً من تخمين سبب أهمية const ، ولكن يمكن للمرء أن يقدم افتراضًا معقولًا.

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

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

الآن عند تمرير متغير إلى وظيفة ، يتعين على المترجم عادة نسخه. من السجل إلى المكدس ، سجل إلى آخر ، إلخ ، هناك عدد غير قليل من الاختلافات. كما أشرت ، قد يختلف موقع المصدر اعتمادًا على وجود أو عدم وجود const.

الآن كما يحدث ، فأنت تمرير محدد التنسيق الخاطئ إلى printf(...), ، يسمى %u بدلاً من %ld. يمكن أن يتسبب ذلك في البحث في المكان الخطأ للحصول على بياناته - ربما في سجل بدلاً من المكدس ، أو العكس. مثل هذا الإجراء يمكن أن يسبب نتائج مفاجئة للغاية. printf(...) يمكن أن تتعثر على سبيل المثال عبر الخاص بك result, ، أو القيم القديمة العشوائية في بعض السجلات. يبدو أنه في الحالة غير الممتدة ، يصادف أن تجد القيمة الصحيحة (على الرغم من أنها قد تكون قد وجدت في المكان الخطأ) ، بينما في حالة const printf(...) فقط يجد القمامة.

ربما لا تكون ذات صلة ، ولكن كن حذرًا: يشير محدد ٪ u لـ printf إلى عدد صحيح غير موقّع ، لكنك تمرر عددًا صحيحًا موقّعًا.

يعالج G ++ هذا جيدًا ولا يذكر تحذيرًا. انها تشكو من printf. يجب أن تستخدم ٪ lu لفترة طويلة. أو حتى أفضل ، باستخدام ٪ LD أو الصب إلى (غير موقعة طويلة int).

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