السلوك المثير للاهتمام لمشغل التحول الأيمن
يُظهر مشغل التحول الأيمن (>>) سلوكًا غريبًا عند التعامل مع قيم التحول الأيمن الكبيرة. خذ بعين الاعتبار البرنامج التالي:
#include
#include
int foo(int a, int b)
{
return a >> b;
}
int bar(uint64_t a, int b)
{
return a >> b;
}
int main()
{
std::cout > 32: " > 32) > (int)32: " > (int)32) الإخراج المتوقع لـ foo(1, 32) سيكون 0، ولكن من المدهش أنه يُرجع 1. يمكن أن يُعزى ذلك إلى ما يلي:
التحول المنطقي مقابل الحسابي Shift
في بنيات x86/x86-64، يقوم مشغل التحول الأيمن في الواقع بإجراء يمينًا منطقيًا Shift، مما يعني أنه يملأ البتات الفارغة بالصفر، بغض النظر عن إشارة المعامل الأيسر. السلوك مشابه لاستخدام >>> b.
تحسين المترجم
في حالة foo(1, 32)، يتم تحويل القيمة 32 إلى int، والذي يتم اقتطاعه بشكل فعال إلى 32 بت. نظرًا لأن الحد الأقصى للقيمة التي يمكن أن يحملها int هي 231-1، فإن الإزاحة الصحيحة هي في الأساس >>> (32 % 32)، والتي يتم تقييمها إلى 0.
غير محدد السلوك
ينص معيار C ذي الصلة على أن "السلوك غير محدد" للإزاحات اليمنى مع عدد أكبر من أو يساوي عرض المعامل الأيسر الذي تمت ترقيته. في هذه الحالة، يكون لكل من 1 >> 32 و(int)1 >> (int)32 عدد أكبر من 32، مما يؤدي إلى نتائج غير متوقعة.
الفرق مع الشريط(1, 32)
يأخذ شريط الوظائف عددًا صحيحًا غير موقّع 64 بت، والذي يضمن أن يكون عرضه أكبر من 32. لذلك، لا يتأثر الإزاحة الصحيحة في الشريط من خلال سلوك غير محدد.
الاستنتاج
يصبح سلوك عامل التحول الأيمن غامضًا عند التعامل مع قيم التحول الكبيرة. في معماريات x86/x86-64، يتم تنفيذ التحول المنطقي لليمين، بينما في ARM، يمكن استخدام تطبيق مختلف. نظرًا لسلوك غير محدد، يجب تجنب نتيجة التحولات لليمين بعدد أكبر من أو يساوي عرض المعامل في التعليمات البرمجية المحمولة.
تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.
Copyright© 2022 湘ICP备2022001581号-3