سؤال

int x=1;
int y=2;
x ^= y ^= x ^= y;

أتوقع أن يتم تبديل القيم. لكنه يعطي x = 0 و y = 1. عندما حاولت بلغة C ، فإنه يعطي النتيجة الصحيحة.

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

المحلول

بيانك مكافئ تقريبًا لهذا النموذج الموسع:

x = x ^ (y = y ^ (x = x ^ y));

على عكس C ، في Java ، يضمن تقييم المعامل الأيسر للمشغل الثنائي قبل المعامل الأيمن. يحدث التقييم على النحو التالي:

x = x ^ (y = y ^ (x = x ^ y))
x = 1 ^ (y = 2 ^ (x = 1 ^ 2))
x = 1 ^ (y = 2 ^ (x = 3))
x = 1 ^ (y = 2 ^ 3)             // x is set to 3 
x = 1 ^ (y = 1)
x = 1 ^ 1                       // y is set to 1
x = 0                           // x is set to 0

يمكنك عكس ترتيب الوسائط إلى كل تعبير XOR بحيث يتم إجراء المهمة قبل تقييم المتغير مرة أخرى:

x = (y = (x = x ^ y) ^ y) ^ x
x = (y = (x = 1 ^ 2) ^ y) ^ x
x = (y = (x = 3) ^ y) ^ x 
x = (y = 3 ^ y) ^ x             // x is set to 3
x = (y = 3 ^ 2) ^ x
x = (y = 1) ^ x
x = 1 ^ x                       // y is set to 1
x = 1 ^ 3
x = 2                           // x is set to 2

هذا إصدار أكثر إحكاما يعمل أيضًا:

x = (y ^= x ^= y) ^ x;

ولكن هذه طريقة مروعة حقًا لمبادلة متغيرين. إنها فكرة أفضل بكثير لاستخدام متغير مؤقت.

نصائح أخرى

مارك صحيح تمامًا حول كيفية تقييمه في جافا. السبب هو JLS §15.7.2., وتقييم المعاملات قبل العملية و §15.7, الذي يتطلب التقييم من اليسار إلى اليمين:

إنه مكافئ (بواسطة §15.26.2, ، مشغلي المهام المركبة) إلى:

x = x ^ (y = y ^ (x = (x ^ y)));

نقوم بتقييم من اليسار إلى اليمين ، ونفعل كلا المعاملين قبل العملية.

x = 1 ^ (y = y ^ (x = (x ^ y))); // left of outer 
x = 1 ^ (y = 2 ^ (x = (x ^ y))); // left of middle 
x = 1 ^ (y = 2 ^ (x = (1 ^ y))); // left of inner
x = 1 ^ (y = 2 ^ (x = (1 ^ 2))); // right of inner
x = 1 ^ (y = 2 ^ (x = 3)); // inner xor (right inner assign)
x = 1 ^ (y = 2 ^ 3); // inner assign (right middle xor)
x = 1 ^ (y = 1); // middle xor (right middle assign)
x = 1 ^ 1; // middle assign (right outer xor)
x = 0; // outer xor (right outer assign)

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

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