الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

مشاكل الدوال في ++c !

مغلق
بدأه Khaled.Alshaya في 2 فبراير 2008 · 11 رد · 2,706 مشاهدة · في المواضيع والدروس
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ,,

كما تعودنا دائماً, سنحاول إلقاء الضوء على نقطة معينة في بحر ++C.

لنلق نظرة على الكود التالي :

cout << 1500;

كما ترون, سيتم طباعة 1500 على الشاشة, و لكن دعنا نتعمق قليلاً في تفاصيل اللغة!

إن جميع البيانات في ++C, لها أنواع معرفة من حيث الحجم و المعاملات التي يمكن أن تتم على ذلك النوع.

فالعدد 1500 في السطر السابق, يجب أن ينتمي لأحد الأنواع العددية في ++C,

لماذا ؟

لأنك بكل بساطة عندما تعرف أي دالة فأنت تذكر أنواع البيانات التي يمكن تمريرها للدالة ( توقيع الدالة ).

هل من الضروري إذاً أن أعرف العدد 1500 في متغير أو ثابت حتى يعمل الكود السابق ؟

الإجابة بكل بساطة, لا.

هنا يأتي دور المترجم, الذي يقوم بتلك العملية تلقائياً, في حالة الأعداد الصحيحة, سيتم التحويل إلى النوع int,

ثم يتم تمرير القيمة ذات النوع, إلى الكائن cout.

إلى هنا أعتقد أن الكلام بسيط و عال العال :)

الآن لنأخذ مسألة بسيطة على هذا الموضوع و سأنتظر حلولكم ,

ألقوا نظرة على الكود التالي :

#include <iostream>

void printX( unsigned int x ){
	std::cout << x;
	return;
}
void printX( int x ){
	std::cout << x;
	return;
}

int main(){
	printX( 5 );
	return 0;
}

تم إعادة تعريف الدالة printX مرة مع النوع int و مرة مع unsigned int ,

الأسئلة ستكون كالتالي :

أي الدالتين سيتم تنفيذها, و لماذا ؟

و إذا اردنا إجبار المترجم على استخدام الدالة الأخرى, ما الذي يجب إضافته ؟

السؤال الأول بسيط جداً, و حله من مقدمة الموضوع,

أما السؤال الثاني فهو المشكلة :D

تحياتي ,,

#2

السلام عليكم:

أي الدالتين سيتم تنفيذها, و لماذا ؟.

كنت اعتقد ان الاولى هي التي تنفذ لكن !

void printX( int x )

جربت وضعتها في الاول وفي الاخير دئما تتنفذ هي فقط.

لماذا؟

اقتباس
في حالة الأعداد الصحيحة, سيتم التحويل إلى النوع int,

و إذا اردنا إجبار المترجم على استخدام الدالة الأخرى, ما الذي يجب إضافته ؟

tvquran_6.gif

#3

طيب حاولت بعده طرق من داخل الدالة الرئسية لم أصل لشئ.

لكن بتغيير بسيط في الدالات يمكن.

void printX( int& x ), void printX( unsigned int x )

سيتم تنفيذ التي البارمتر ممرر بالقيمة

اما التى البارمتر ممرر بالمرجع لن يتم تنفيذها.

لماذا ؟

الله اعلم.

تم تعديل هذه المشاركة بواسطة محمد علاء الدين في 13 أغسطس 2010 في 22:00

tvquran_6.gif

#4

طرأت لي الفكرة، وسأطرحها...

ربما لنجبر الدالة

void printX( unsigned int x ){

على العمل نضع قيمة أكبر من 32,767 وأقل من 65,535 فهذه القيم لن يستطيع الـ int يحملها.

#5
#include <iostream>

void printX( unsigned int x ){
	std::cout << x;
	return;
}
void printX( int x ){
	std::cout << x;
	return;
}

int main(){
	printX( unsigned int(-5) );
	return 0;
}

:)

من أقوال الأئمة

الإمام علي بن أبي طالب -رضي الله عنه-: "الناس ثلاثة : فعالم رباني ، ومتعلم على سبيل النجاة ، وهمج رِعاع غوغاء أتباع كل ناعق ، يميلون مع كل ريح ، لم يستضيئوا بنور العلم ، ولم يلجئوا إلى ركن وثيق".

الإمام مالك -رحمه الله- : " لن يصلح آخر هذه الأمة إلا بما أصلح به أولها ".

الإمام الأوزاعي -رحمه الله- : " عليك بآثار من سلف وإن رفضك الناس وإياك وآراء الرجال وإن زخرفوه لك بالقول ".

الإمام الفضيل بن عياض -رحمه الله- : " عليك بطرق الهدى و لا يضرك قلة السالكين و إياك و طرق الضلالة ولا يغرك كثرة الهالكين ".

علامة الزمان الإمام الألباني -رحمه الله- : " إن الخلاص إلى أيدي هؤلاء الشباب يتمثل في أمرين لا ثالث لهما ؛ التصفية والتربية ".

وكل خير في اتباع من سلف وكل شر في ابتداع من خلف

#6

الله يسامحك يا باسم ... جئت إلى الحاسوب جريا لأقول نضع تحويل Casting لأفاجأ بأنك وضعت الحل :(

#7
اقتباس
على العمل نضع قيمة أكبر من 32,767 وأقل من 65,535 فهذه القيم لن يستطيع الـ int يحملها.

تقصد أكبر من 2147483647

لكن هذا سيعطي error

وإذا كتبت 2147483647+1 سيقوم بطباعة عدد سالب

اقتباس
الله يسامحك يا باسم ... جئت إلى الحاسوب جريا لأقول نضع تحويل Casting لأفاجأ بأنك وضعت الحل

أنا قلت لنفسي أسبقكم هذه المرة

مرة من نفسي

من أقوال الأئمة

الإمام علي بن أبي طالب -رضي الله عنه-: "الناس ثلاثة : فعالم رباني ، ومتعلم على سبيل النجاة ، وهمج رِعاع غوغاء أتباع كل ناعق ، يميلون مع كل ريح ، لم يستضيئوا بنور العلم ، ولم يلجئوا إلى ركن وثيق".

الإمام مالك -رحمه الله- : " لن يصلح آخر هذه الأمة إلا بما أصلح به أولها ".

الإمام الأوزاعي -رحمه الله- : " عليك بآثار من سلف وإن رفضك الناس وإياك وآراء الرجال وإن زخرفوه لك بالقول ".

الإمام الفضيل بن عياض -رحمه الله- : " عليك بطرق الهدى و لا يضرك قلة السالكين و إياك و طرق الضلالة ولا يغرك كثرة الهالكين ".

علامة الزمان الإمام الألباني -رحمه الله- : " إن الخلاص إلى أيدي هؤلاء الشباب يتمثل في أمرين لا ثالث لهما ؛ التصفية والتربية ".

وكل خير في اتباع من سلف وكل شر في ابتداع من خلف

#8

السلام عليكم ,,

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

هذه الثوابت العددية إذا كانت أعداداً صحيحة, سيتم تحويلها تلقائياً إلى أعداد من النوع int,

جميع الأنواع في ++C هي أنواع تحمل أعداداً صحيحة, إلا النوع bool لأنه حالة خاصة من النوع char و قيمه عبارة عن ثوابت, و الأعداد الحقيقة float and double,

جميع الأنواع الباقية يمكن أن تمثل على أنها أعداد صحيحة موجبة فقط أو أنها أعداد صحيحة (بقسمها الموجب و السالب بالطبع)

لانريد التفصيل في كيفية تمثيل الأعداد السالبة في المعالج, و لكن أغلب المعالجات حالياً تمثل بالـ Two's Complements,

هناك رمز يستعمل في التفريق بين النوع signed int و النوع unsigned int و هو الحرف U سواء كان كبيراً U أو صغيراً u ملحقاً بالعدد,

على سبيل المثال, لاستدعاء الدالة التي تحتوي على الوسيط x من النوع unsigned int كل ما علينا هو كتابة التالي :

printX( 5U );

أو بشكل آخر :

printX( 5u );

و بكل بساطة سيعرف المترجم أنك تقصد أن هذا العدد unsigned,

هل هذا الشيء مهم إلى هذه الدرجة, نعم!

صحيح أن هذا الشيء ليس مذكوراً في الكتب التي تعلم اللغة, إلا أن التفريق بين النوعين signed و unsigned مهم جداً و قد يؤدي إرسال عدد signed لدالة تستقبل عدد unsigned إلى تحويل منطق الدوال المفترض لحالات غريبة!

يمكننا أن نستعرض بعض الأمثلة إذا أردتم,

بالنسبة لعملية التحويل بين الأنواع Casting. فهي ليست من المفترض أن تحل محل هذه الطريقة, و لكنها لتحويل قيمة من نوع لآخر, دعنا نستعرض المثال لنرى الفرق :

printX( 22U );

عندما سيقرأ المترجم العدد 22 سيقوم بتحويله للنوع unsigned int مباشرة,

أما في الحالة التالية :

printX( static_cast<unsigned int>(22) );

فسيتم التحويل للنوع unsgined int بعد أن يحول العدد 22 للنوع signed int,

على كل حال قد لا يكون هناك فرق بين الطريقتين, لأن المترجم قد يقوم بعملية Optimization و يعتبر العدد unsigned مباشرة,

و لكنها لمحة فقط لرؤية الدقة في تعريف لغة ++C نفسها, و كيف تفرق بين المفاهيم القريبة من بعضها بطرق مختلفة,

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

تحياتي ,,

#9

السلام عليكم:

ايضا مرة اخرى.

اذا كتبت في الدالة الرئسية:

printX( signed(5) );

راح يستخدم دائما 
void printX( int x )

واذا كتبت

printX( unsigned(5) ) ;
 راح يستخدم 
void printX( unsigned int x )

تم تعديل هذه المشاركة بواسطة محمد علاء الدين في 13 أغسطس 2010 في 22:03

tvquran_6.gif

#10

من سالب 2147483647 إلى موجب 2147483647 هذا مجال أرقام int (ما كتبته في ردي السابق كان حسب نظام 16 بت)

الآن ال unsigned int له نفس الحجم بكن بدون سالب أي كل الأرقام موجبة من 0 إلى 2147483647 2x أي 4294967294.

يعني رقم أكبر من 2147483647 يعطينا قيم سالبة،في int العادي (Overflow) لـــــكن الـ unsigned int لا يجمل أرقام سالبة لهذا كل المساحة التي أعطيت للأرقام السالبة سوف تضاف على الأرقام الموجبة:

سالب ------------------------------------------------- 0 -----------------------------2147483647|نهاية المجال <-----int ا

.

.

0 ----------------------------------------------2147483647-----------------------4294967294| نهاية المجالunsigned

#11

السلام عليكم

هل الكتابة بهذه الطريقه

signed(5)

تعتبر تحويل ؟

تم تعديل هذه المشاركة بواسطة فهدالشلوي في 2 فبراير 2008 في 11:36

tvquran_6.gif

#12

السلام عليكم أخ فهد,,

بالنسبة للطريقة التي تذكرها فهي ليست موجودة في ++C, أعتقد أنها طريقة C, و لكن بعض المترجمات تسمح بكتابة طريقتك,

يوجد في ++C طريقة للتحويل بين الأعداد تسمى static_casting كما ذكرت في ردي السابق,

تحياتي ,,

هذا الموضوع مغلق.

مواضيع مشابهة