سؤال

نسخة الجلسة:

>type lookma.c
int main() {
  printf("%s", "no stdio.h");
}

>cl lookma.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

lookma.c
Microsoft (R) Incremental Linker Version 8.00.50727.762
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:lookma.exe
lookma.obj

>lookma
no stdio.h
هل كانت مفيدة؟

المحلول

في وضع الامتثال الصارم (وهذا يعني "نظريًا")، يمكنك استدعاء سلوك غير محدد (وهو أمر سيئ) عند استدعاء دالة تأخذ عددًا متغيرًا من الوسائط دون إعلان نموذج أولي للوظيفة في النطاق.وهذا يعني أنه يُسمح للمترجم بفعل أي شيء يريده باستخدام البرنامج الذي يستخدمه printf() بدون النموذج الأولي من #include <stdio.h> أو إعلان مماثل."أي شيء يحبه" يتضمن العمل بشكل صحيح كأحد الخيارات؛يبدو أن هذا هو الخيار الذي اختاره المثال الخاص بك.

من الناحية العملية، ستعمل التعليمات البرمجية بشكل جيد مع معظم المترجمين العمليين حتى بدون الإعلان الرسمي عن printf() وظيفة.

كما أشار qrdl، تم العثور على الوظيفة لأن مترجم C يرتبط بمكتبة C.

لاحظ أن تعليق Chris Young حول C99 و"implicit int" دقيق، ولكن القاعدة المتعلقة بـ "يجب أن يكون لوظائف الوسائط المتغيرة نموذج أولي في النطاق" تنطبق على كل من C89 وC99.لا تعمل معظم المترجمات في وضع التوافق الصارم مع C99 افتراضيًا نظرًا لوجود الكثير من التعليمات البرمجية التي لا يمكن تجميعها بهذه الطريقة.

علق كريس يونغ:

للتوضيح، كان تعليقي على إزالة C99 للإعلانات الضمنية.بقولك "int ضمنيًا"، أعتقد أنك تشير إلى ميزة C89 المتمثلة في السماح بإعلانات مثل foo(void);ليعني int foo(void)؛، وهو شيء تمت إزالته أيضًا من C99.

كريس بالطبع على حق.تمت إزالة ميزتين من "الإعلان الضمني" من معيار C99.تسردها مقدمة المعيار على النحو التالي:

  • إزالة ضمنية int
  • إزالة إعلان الوظيفة الضمنية

لم أكن أفكر (وبالتالي لم أكتب) بوضوح كافٍ.ومع ذلك، يتطلب كل من C89 وC99 نموذجًا أوليًا في نطاق الوظائف التي تأخذ عددًا متغيرًا من الوسائط.

لتوضيح:

extern int pqr();
int main(void)
{
    int i = pqr(1, 3);
    return i;
}

بدون السطر الأول، هذا جزء C89 صحيح مع إعلان ضمني للوظيفة pqr() كدالة تقوم بإرجاع عدد صحيح (مع وسائط غير محددة).إذا تم استبدال السطر الأول بـ extern pqr();, ، فهذا جزء صحيح من C89 مع إعلان صريح لـ pqr() كدالة تقوم بإرجاع عدد صحيح (مع وسائط غير محددة)، ولكن نوع الإرجاع هو "ضمني". int'.كما هو مكتوب، تم التصريح عن الوظيفة بشكل صريح ولها صيغة صريحة int نوع الإرجاع - لكنه لا يزال يحتوي على وسائط غير محددة.أعتقد أن هذا صحيح C99 - وإن لم يكن مرغوبًا فيه تمامًا.بالتأكيد دول مجلس التعاون الخليجي (3.4.4) يقبلها مع الخيارات '-std=c99 -pedantic".من الناحية المثالية، يجب أن يتضمن إعلان الوظيفة النموذج الأولي الكامل.(و إذا pqr() تم تعريفها باستخدام علامات الحذف، وسيكون هذا النموذج الأولي مطلوبًا نظريا!)

نصائح أخرى

وأنت قد الموسومة أصلا هذا C ++، ولكن على ما يبدو أن يكون هناك برنامج C. وC توفير تلقائيا إعلانا ضمنيا عن وظيفة إذا لم يكن هناك نموذج في النطاق (مثل ويرجع ذلك إلى إغفال # تشمل ). إن إعلان ضمني على النحو التالي:

int printf();

وهذا يعني أن printf هو دالة تقوم بإرجاع عدد صحيح ويمكن أن تتخذ أي عدد من الحجج. حدث هذا النموذج للعمل من أجل مكالمتك. يجب أن تتضمن #

وأخيرا، أود أن أضيف أن مستوى C الحالي (ISO / IEC 9899: 1999 أو بالعامية "C99") لا على لا السماح الإعلانات الضمنية، وهذا من شأنه أن البرنامج لا تتفق. تم إزالة الإعلانات الضمنية. أعتقد المترجم الخاص بك لا يدعم C99. يتطلب C ++ أيضا نماذج الصحيحة ولا تفعل الإعلانات الضمنية.

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

والفشل لتشمل النتائج رأس المناسبة في استخدام وظيفة التي لم نموذج أولي يمكن أن تؤدي إلى مشاكل، كما يفترض C مترجم أن وظيفة من دون نموذج بإرجاع int ويأخذ عدد متغير من الوسائط. لذلك دائما وتشمل رأس - انها سياج سلامتك

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