متى يجب عليك استخدام وحدات الماكرو بدلاً من الوظائف المضمنة؟

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

  •  08-07-2019
  •  | 
  •  

سؤال

في سابقة سؤال ما اعتقدت أنه إجابة جيدة تم التصويت عليه لصالح الاستخدام المقترح لوحدات الماكرو

#define radian2degree(a) (a * 57.295779513082)
#define degree2radian(a) (a * 0.017453292519)

بدلاً من الوظائف المضمنة.يرجى المعذرة على سؤال المبتدئ، ولكن ما هو الشر في وحدات الماكرو في هذه الحالة؟

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

المحلول

وهناك بضعة أشياء شريرة بدقة حول وحدات الماكرو.

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

وأنها لا تأخذ الحجج بالمعنى العادي. يمكنك كتابة وظيفة من شأنها أن تأخذ قيمتين int والعودة الحد الأقصى، لأن الحجج وسيتم تقييم مرة واحدة والقيم تستخدم بعد ذلك. لا يمكنك كتابة ماكرو للقيام بذلك، لأنها سوف تقيم حجة واحدة على الأقل مرتين، وتفشل مع شيء من هذا القبيل max(x++, --y).

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

في الحالة الخاصة بك، تحتاج قوسين:

#define radian2degree(a) (a * 57.295779513082)

يجب أن يكون

#define radian2degree(a) ((a) * 57.295779513082)

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

نصائح أخرى

تناقش معظم الإجابات الأخرى سبب كون وحدات الماكرو شريرة بما في ذلك كيف أن المثال الخاص بك به عيب شائع في استخدام الماكرو.وإليك رأي ستروستروب: http://www.research.att.com/~bs/bs_faq2.html#macro

لكن سؤالك كان يسأل عن وحدات الماكرو التي لا تزال مفيدة.هناك بعض الأشياء التي تكون فيها وحدات الماكرو أفضل من الوظائف المضمنة، وهذا هو المكان الذي تقوم فيه بأشياء لا يمكن تنفيذها ببساطة باستخدام الوظائف المضمنة، مثل:

  • لصق رمزي
  • التعامل مع أرقام الأسطر أو ما شابه (مثل إنشاء رسائل خطأ في assert())
  • التعامل مع الأشياء التي ليست تعبيرات (على سبيل المثال، عدد تطبيقات offsetof() استخدم استخدام اسم النوع لإنشاء عملية إرسال)
  • الماكرو للحصول على عدد عناصر المصفوفة (لا يمكن القيام بذلك باستخدام دالة، حيث يتحول اسم المصفوفة إلى مؤشر بسهولة شديدة)
  • إنشاء أشياء تشبه الوظائف "نوعية متعددة الأشكال" في لغة C حيث لا تتوفر القوالب

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

لقد انتقلت أيضًا إلى استخدام التعدادات للثوابت الرقمية المسماة بدلاً من ذلك #define.

بالنسبة لهذا الماكرو المحدد، إذا استخدمته على النحو التالي:

int x=1;
x = radian2degree(x);
float y=1;
y = radian2degree(y);

لن يكون هناك فحص للنوع، وسيحتوي x وy على قيم مختلفة.

علاوة على ذلك، الكود التالي

float x=1, y=2;
float z = radian2degree(x+y);

لن تفعل ما هو رأيك، لأنه سوف يترجم إلى

float z = x+y*0.017453292519;

بدلاً من

float z = (x+y)+0.017453292519;

وهي النتيجة المتوقعة.

هذه مجرد أمثلة قليلة على سوء السلوك وسوء استخدام وحدات الماكرو.

يحرر

يمكنك رؤية مناقشات إضافية حول هذا الموضوع هنا

غالبًا ما يتم إساءة استخدام وحدات الماكرو ويمكن للمرء بسهولة ارتكاب الأخطاء عند استخدامها كما هو موضح في المثال الخاص بك.خذ التعبير راديان 2 درجة (1 + 1):

  • مع الماكرو سيتم توسيعه إلى 1 + 1 * 57.29...= 58.29...
  • مع دالة سيكون ما تريده أن يكون، أي (1 + 1) * 57.29...= ...

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

#define radian2degree(a) ((a) * 57.295779513082)

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

وإذا كان ذلك ممكنا، دائما استخدام وظيفة المضمنة. هذه هي typesafe ولا يمكن إعادة تعريف بسهولة.

ويعرف يمكن redfined غير معروف، وليس هناك نوع التحقق.

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

وحدات الماكرو شريرة لأنك قد ينتهي ويمر أكثر من متغير أو العددية لها، وهذا قد حل في السلوك غير المرغوب فيه (تعريف ماكرو كحد أقصى لتحديد الحد الأقصى بين أ و ب ولكن تمرير ++ وب ++ إلى الماكرو و نرى ما سيحدث).

إذا الدالة ستكون inlined على أي حال، ليس هناك فرق بين أداء وظيفة وماكرو. ومع ذلك، هناك العديد من الاختلافات بين سهولة الاستخدام وظيفة وماكرو، وكلها يفضلون استخدام وظيفة.

إذا كنت بناء الماكرو بشكل صحيح، لا توجد مشكلة. ولكن إذا كنت تستخدم وظيفة، فإن المترجم تفعل ذلك بشكل صحيح بالنسبة لك في كل مرة. وذلك باستخدام وظيفة يجعل من الصعب كتابة التعليمات البرمجية سيئة.

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