هل النماذج الأولية مطلوبة لجميع الوظائف في C89 أو C90 أو C99؟

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

  •  10-07-2019
  •  | 
  •  

سؤال

لكي تكون متوافقة حقًا مع المعايير، هل يجب أن تحتوي جميع الوظائف في لغة C (باستثناء الوظيفة الرئيسية) على نموذج أولي، حتى لو تم استخدامها فقط بعد تعريفها في نفس وحدة الترجمة؟

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

المحلول

يعتمد الأمر على ما تعنيه بـ "متوافق حقًا مع المعايير".ومع ذلك، الإجابة المختصرة هي "من الجيد التأكد من أن جميع الوظائف لديها نموذج أولي في نطاقها قبل استخدامها".

تشير الإجابة الأكثر تأهيلاً إلى أنه إذا كانت الوظيفة تقبل الوسائط المتغيرة (لا سيما printf() مجموعة الوظائف)، فيجب أن يكون النموذج الأولي في نطاقه ليكون متوافقًا بشكل صارم مع المعايير.وينطبق هذا على C89 (من ANSI) وC90 (من ISO؛نفس C89 باستثناء ترقيم الأقسام).بخلاف وظائف "varargs"، فإن الوظائف التي تُرجع ملفًا int ليس من الضروري التصريح عنها، والوظائف التي تُرجع شيئًا آخر غير int تحتاج إلى إعلان يوضح نوع الإرجاع ولكن لا تحتاج إلى النموذج الأولي لقائمة الوسائط.

ومع ذلك، لاحظ أنه إذا كانت الوظيفة تأخذ وسيطات تخضع لـ "الترقيات العادية" في حالة عدم وجود نماذج أولية (على سبيل المثال، دالة تأخذ char أو short - وكلاهما محول إلى int;ربما يكون الأمر الأكثر جدية هو الوظيفة التي تأخذ float بدل من double)، ثم هناك حاجة إلى نموذج أولي.كان المعيار متساهلًا بشأن هذا للسماح بتجميع كود C القديم ضمن برامج التحويل البرمجي المتوافقة القياسية؛لم تتم كتابة التعليمات البرمجية القديمة للقلق بشأن ضمان الإعلان عن الوظائف قبل الاستخدام - وبحكم التعريف، لم تستخدم التعليمات البرمجية القديمة النماذج الأولية لأنها لم تصبح متاحة في لغة C حتى كان هناك معيار.

C99 لا يسمح بـ "int ضمنيًا"... وهذا يعني كلتا الحالتين الغريبتين مثل "static a;"( ان int بشكل افتراضي) وكذلك إعلانات الوظائف الضمنية.تم ذكرها (إلى جانب حوالي 50 تغييرًا رئيسيًا آخر) في مقدمة ISO/IEC 9899: 1999 ، والتي تقارن هذا المعيار بالإصدارات السابقة:

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

في ISO/IEC 9899:1990، §6.3.2.2 استدعاءات الوظائف معلن:

إذا كان التعبير الذي يسبق قائمة الوسيطة الأقواس في استدعاء دالة يتكون فقط من معرف ، وإذا لم يكن أي إعلان مرئيًا لهذا المعرف ، فسيتم إعلان المعرف ضمنيًا تمامًا كما لو كان ، في كتلة الأعمق التي تحتوي على استدعاء الوظيفة ، الإعلان:

extern int identifier();

ظهر.38

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

هذه الفقرة مفقودة في معيار 1999.لم أتتبع (حتى الآن) التغيير في الإسهاب الذي يسمح بذلك static a; في C90 ولا يسمح به (يتطلب static int a;) في C99.

لاحظ أنه إذا كانت الوظيفة ثابتة، فقد يتم تعريفها قبل استخدامها، ولا يلزم أن يسبقها إعلان.يمكن إقناع دول مجلس التعاون الخليجي بالكتابة إذا تم تعريف وظيفة غير ثابتة دون إعلان يسبقها (-Wmissing-prototypes).

نصائح أخرى

A <م> النموذج هو تعريف الدالة التي تحدد أنواع المعلمات الدالة.

وقبل ANSI C (اللغة التي وصفها الطبعة الأولى من كيرنيغان وريتشي "وC لغة البرمجة" 1978) لم يكن لديهم نماذج أولية. لم يكن من الممكن لإعلان وظيفة لوصف عدد أو أنواع من المعلمات. كان ليصل إلى المستدعي لتمرير العدد الصحيح ونوع من الحجج.

وANSI C عرض "نماذج"، والإعلانات التي تحدد أنواع المعلمات (ميزة اقترضت من أوائل C ++).

واعتبارا من C89 / C90 (معايير ANSI و ISO تصف نفس اللغة)، انها قانونية استدعاء دالة مع أي إعلان مرئية. وتقدم إعلانا ضمنيا. إذا كان إعلان ضمني غير متوافق مع تعريف الفعلي (ويقول واصفا sqrt("foo")، ثم هي غير معرفة السلوك. لا هذا إعلان ضمني ولا إعلانا غير النموذج يمكن أن تكون متوافقة مع وظيفة variadic، لذلك أي استدعاء دالة variadic (مثل printf أو scanf) يجب أن يكون النموذج مرئية.

وانخفض C99 الإعلانات الضمنية. أي دعوة إلى وظيفة دون إعلان للعيان هو انتهاك قيد، والتي تتطلب مترجم التشخيص. ولكن هذا الإعلان لا يزال غير مطلوب أن تكون نموذجا أوليا. يمكن أن يكون إعلانا على الطراز القديم التي لا تحدد أنواع المعلمة.

وجعلت C11 أي تغييرات كبيرة في هذا المجال.

وهكذا حتى اعتبارا من ISO C القياسية عام 2011، على الطراز القديم الإعلانات وظيفة والتعاريف (التي كانت "الزائل" منذ عام 1989) لا تزال المسموح بها في المطابقة التعليمات البرمجية.

لكافة إصدارات C تعود إلى عام 1989، على سبيل الاسلوب، هناك سبب وجيه جدا عدم استخدام نماذج لجميع الوظائف. يتم الاحتفاظ الإعلانات على الطراز القديم والتعاريف فقط لتجنب كسر القانون القديم.

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

.

نعم، يجب أن يكون كل وظيفة نموذج أولي، ولكن قد تظهر أن النموذج إما في اعلان منفصل أو كجزء من تعريف الدالة. تعريفات الدالة مكتوبة في C89 وحتى يكون طبيعيا النماذج، ولكن إذا كنت أكتب أشياء في K & R النمط الكلاسيكي، على النحو التالي:

main (argc, argv)

  int argc;
  char **argv;

{
  ...
}

وبعد ذلك تعريف الدالة لا يوجد نموذج. إذا كنت أكتب ANSI C (C89) أسلوب، على النحو التالي:

main (int argc, char **argv) { ... }

وبعد ذلك تعريف الدالة لديه النموذج.

وهناك معلومات لطيفة عند كتابة وظائف جديدة لكتابة لهم رأسا على عقب مع رئيسي في أسفل حتى عندما قمت بتغيير رأيك حول وسائط وظيفة أو العودة نوع لم يكن لديك لإصلاح النموذج أيضا. تحديد باستمرار النماذج، والتعامل مع كل التحذيرات المترجم عندما يكونون خارج التاريخ يحصل مملة حقا.

وبمجرد الانتهاء من المهام الخاصة بك تعمل بسلاسة معا نقل رمز إلى وحدة نمطية اسمه جيدا، ووضع النماذج الأولية في ملف .h الذي يحمل نفس الاسم. أنه يوفر الوقت خطيرة. أكبر مساعدات الإنتاجية وجدتها في 5 سنوات.

على حد علمي (في ANSI C89/ISO C90)، لا.أنا غير متأكد من C99؛ومع ذلك، أتوقع نفس الشيء.

ملاحظة شخصية: أنا أكتب نماذج أولية للوظيفة فقط عندما...

  1. أحتاج إلى (عندما يستدعي A() B()) و B() يستدعي A())، أو
  2. أقوم بتصدير الوظيفة؛وإلا فإنه يبدو غير ضروري.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top