c - لغة - شرح جافا سكربت بالعربي pdf




C: نوع التحويل عند تمرير وسيطة على استدعاء دالة (3)

من لغة البرمجة C الطبعة الثانية:

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

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

من أجل التحقق من فرضي، أنا جمعت التعليمات البرمجية التالية:

#include <stdio.h>

main()
{
     unsigned char c = 'Z';
     float number = 3.14f;
     function_call(c, number);
}

void function_call(char c, float f)
{
}

بعد التجميع أحصل على التحذيرات التالية:

typeconversion.c: 11: وارنينغ: أنواع متضاربة ل 'function_call'

typeconversion.c: 7: وارنينغ: إعلان ضمني سابق من 'function_call' هنا

تخميني هو c وتم تحويل عدد إلى إنت ومضاعفة على استدعاء وظيفة، ثم تم تحويلها مرة أخرى إلى شار وتطفو. هل هذا ما حدث فعلا؟

https://code.i-harness.com


فالقوالب لا صلة لها بالموضوع، فهي النموذج الأولي (ربما الضمني) الذي يهمنا.

void foo(short s) {
    // do something
}

int main(void) {
  signed char c = 'a';

  foo(c);  // c is promoted to short by explicit prototype
  bar(c);  // c is promoted to int by implicit prototype
}

void bar(int i) {
    // do something
}

عندما يقول الكتاب "حجة الدعوة وظيفة هو تعبير" فهذا يعني أن نفس قواعد الترويج النوع ينطبق. قد يكون من الأسهل أن نفهم إذا كنت تفكر في وسيطة الدالة كتعيين ضمني للمتغير المحدد في نموذج الدالة. على سبيل المثال في الدعوة إلى foo() أعلاه هناك short s = c ضمنية short s = c .

هذا هو السبب في يلقي لا يهم. ضع في اعتبارك مقتطف الشفرة التالي:

signed char c = 'a';
int i = (short) c;

هنا يتم الترويج قيمة c أولا إلى short (صراحة) ثم إلى int (ضمنا). قيمة i سوف يكون دائما int .

أما بالنسبة ل char و short تصبح int float تصبح double يشير إلى أنواع الافتراضي لنماذج الوظائف الضمنية. عندما يرى المترجم مكالمة إلى وظيفة قبل أن يرى إما نموذج أولي أو تعريف وظيفة فإنه يولد نموذجا تلقائيا. يتم افتراضها إلى int لقيم عدد صحيح double لقيم نقطة العائمة.

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


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

ما حدث هو أنه عندما كتبت

function_call(c, number);

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

function_call(int, double)

ثم عندما يرى

function_call(char c, float f)

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

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


الجميع غاب شيء واحد. في إسو C نموذج إسو-سينتاكس يلغي تعزيز الوسيطة الافتراضية.

وفي هذه الحالة يسمح للمترجم بتوليد كود مختلف (!) يستند فقط على أسلوب التعريف. هذا يحصل لك التوافق K & R، ولكن لا يمكنك دائما استدعاء بين مستويات اللغة إلا إذا كنت قد كتبت رمز إسو كما K & R تتوقع أو تعديل كود K & R لرؤية النماذج إسو.

جربه باستخدام سيسي -S -O ...

extern float q; void f(float a) { q = a; }
movl    8(%ebp), %eax
movl    %eax, q

extern float q; void f(a) float a; { q = a; } // Not the same thing!
fldl    8(%ebp)
fstps   q




type-conversion