2014-10-09 4 views
4
public class Main 
{ 
    public static void main(String[] args) 
    { 
     int a,b,c,d; 
     a=1;b=2; 
     a^=b^=a^=b; 
     System.out.println(a+" "+b); 
     c=1;d=2; 
     c^=d; 
     d^=c; 
     c^=d; 
     System.out.println(c+" "+d); 
    } 
} 

Я использую a^b^= a^= b для замены a и b. Однако выход из этой программыa^= b^= a^= b в Java кажется неправильным

0 1 
2 1 

Я новый один в Java, и я не знаю, почему это 0. Является ли это ошибка в моей среде выполнения Java? Или что-то особенное в Java я не знаю? Вот java -версия.

java version "1.7.0_65" 
OpenJDK Runtime Environment (fedora-2.5.2.5.fc20-x86_64 u65-b17) 
OpenJDK 64-Bit Server VM (build 24.65-b04, mixed mode) 

К сожалению, это мой первый вопрос на переполнение стека ... если я забыл некоторые правила, скажите мне, пожалуйста, спасибо.

+2

В третий раз, когда вы его написали, вы написали это по-другому. – keyser

+10

Мой совет? Не пишите такой код. Это победитель кода обфускации. Ваша цель должна заключаться в том, чтобы писать как можно яснее. – duffymo

+1

Я знаю, что это не очень хороший способ кодирования, но мне интересно, что случилось, когда я использовал a = b^= a^= b. Я не думаю, что хороший программист тоже это сделает. –

ответ

4

Давайте упростим вместе

int a = 1; 
int b = 2; 
a ^= (b ^= (a ^= b)); 
System.out.println(a + " " + b); 

то же самое, как говорят

int a = 1; 
int b = 2; 
int a_tmp = a; 
a = a_tmp^(b ^= (a ^= b)); 
System.out.println(a + " " + b); 

Ваш код при условии, что мы обрабатываем а^= (Ь = (а^= Ь)) перед a^= (b^= (a^= b)), но это неправильно. Я не знаю, где это будет работать. Но, как указано @duffymo, не пытайтесь это делать дома.

+0

Yep, * any * statement с несколькими присваиваниями в лучшем случае опасен. И операторы «оператор-равны» вдвойне опасны. –

0

Убедитесь, что вы смотрите на свой порядок операций. Это может быть то, что происходит:

true^true = false 
true^false = true 
false^true = true 
false^false = false 

a^=b^=a^=b; 

Работа справа налево: 0001^0010^0001^0010 взять первые 2 дальняя правая 0001^0010 = 0011. Теперь продолжайте двигаться влево принять свой ответ на следующий элемент 0010^0011 = 0001 теперь перемещается влево еще раз. 0001^0001 = 0000, поэтому a = 0000 или 0.
Теперь возьмите выражение b: 0010^0001^0010 теперь сделайте то же самое справа налево. 0001^0010 = 0011 теперь переместиться влево 0010^0011 = 0001, так что b = 0001 или 1. Поэтому, когда вы печатаете a = 0000 или 0 и b = 0001 или 1. Это побитовые исключительные операции ИЛИ, убедитесь, что смотрите порядок операций тщательно.

+0

Ваши объяснения неверны. Вы считаете, что значения переменных еще не изменились, вставив 0001^0010^0001^0010 в качестве выражения для оценки. Но на самом деле это^0010^0001^0010. Потому что после оценки первого xor 0001^0010 также изменяется a. Таким образом, это больше не 0001, а 0011 для первой переменной в вашем заявлении. OP фактически является правильным, ожидая 2 и 1 как значения (согласно спецификациям). Я позже опубликую ответ, почему вместо этого получается 0 и 1. – Juru

Смежные вопросы