سؤال

لدي وظيفة مثل

void printMe (void *i)
{
    printf("%d", i);
}

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

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

المحلول

س1: لذا فإن السؤال هو، هل يمكننا إنشاء دالة في لغة C من شأنها طباعة العنصر الذي يمثل معلمتها

أ:ليس بالطريقة التي تريدها.سيكون عليك تمرير المعلومات إلى الوظيفة، وإخبارها بنوع البيانات التي تقوم بتمريرها.

س2: وإذا كانت الإجابة بنعم فكيف يكون هذا ممكنا لأنه يراوغني تماما في هذه اللحظة.

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

  1. تمرير هيكل يحتوي على
    المؤشر والمعلومات حول ما
    يشير المؤشر إلى (على سبيل المثالالتعداد).
  2. تمرير معلمة إضافية مع معلومات حول ما يشير إليه المؤشر

نظرًا لأن الرمز موجود، فإن الشيء الوحيد الذي يمكنك طباعته هنا هو العنوان الذي أشير إليه.

يشير المؤشر الفارغ إلى البيانات الأولية، ويفترض printf أنك تعرف نوع البيانات التي تطبعها، وليس لديه أي ذكاء ولا يمكنه "معرفته" نيابةً عنك.

بكل بساطة.

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

أتمنى أن يساعدك هذا.

أيضًا ..."لا يوجد تحميل زائد في لغة C مثلما أستخدمه عادةً في لغة C++"

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

cout << i;

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

cout << *(int*)i;

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

printMe(int i){...}
printMe(double d){...}
printMe(char c){...}
printMe(char* string){...}

في لغة C تحتاج فقط إلى إعطاء هذه الوظائف أسماء محددة

printInt(int i){...}
printDouble(double d){...}
printChar(char c){...}
printString(char* string){...}

نصائح أخرى

لبداية، كنت تطبع المؤشر، وليس ما يشير إليه. لطباعة محتويات الفعلية، تحتاج إلى تمرير *i إلى printf، وليس i.

إذا كنت تريد حقا أن تفعل هذا، حل واحد هو:

void printMe (void *p, int typ) {
    switch(typ) {
        case TYP_INT: printf("%d", *((int*)p)); break;
        case TYP_CHR: printf("%c", *((char*)p)); break;
        /* and so on ... */
    }
}
<اقتباس فقرة>   

ولذا فإن السؤال هو هذا، يمكننا إنشاء دالة في C التي ستطبع العنصر الذي هو انها معلمة

ونعم نستطيع. مثل هذه الوظيفة هي بالفعل جزء من المكتبة القياسية - انه دعا printf؛)

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

إذا كنت تحاول طباعة قيمة المؤشر، الاستخدام الصحيح هو printf("%p", i);. و'د' محدد هو الأعداد الصحيحة، و'ع' هو للمؤشرات. انها مسؤوليتكم للحصول على هذه صحيحة، والأشياء السيئة يمكن أن يحدث إذا كنت نخلط بينها.

وأنا لا أعرف لماذا هذا من شأنه أن تفشل لشار * وليس عدد صحيح *، وأنه من الممكن لديك مشاكل أخرى تسبب هذا. إذا كان لا يزال فشل مع٪ ص، شيء آخر حصل عابث. نرى ما اذا كان يمكنك تثبيت نوعا من برنامج رصد الذاكرة للتحقق من مؤشرات متدلية أو ضعف مجانا () ق، لأنه في هذه النقطة الأموال الذكية هي تلك التي قمت تلف الذاكرة في مكان ما.

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