Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> x ^= y ^= x ^= y; 
:(
    Опции темы
kurzon
Дата 20.9.2007, 12:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 307
Регистрация: 12.8.2007

Репутация: -8
Всего: -11



Код

using System;

internal class Test
{
    private static void Main(string[] args)
    {
        int x = 1984; // (0x7c0)
        int y = 2001; // (0x7d1)
        x ^= y ^= x ^= y;
        Console.WriteLine("x = " + x + "; y = " + y);
    }
}

Ето побитное додавание с права на ливо
Пачему компилятор выводит: x=0; y=1984;
Обсянить поподробней?




Это сообщение отредактировал(а) kurzon - 20.9.2007, 13:00
PM MAIL   Вверх
ivashkanet
Дата 20.9.2007, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 47
Всего: 149



Цитата(kurzon @  20.9.2007,  12:59 Найти цитируемый пост)
        x ^= y ^= x ^= y;

kurzon, извини пожалуйста, но в подобной белиберде сам разбирайся.
Неужели тяжело было разбить то же самое на несколько строчек?
PM MAIL WWW ICQ   Вверх
Sartorius
Дата 20.9.2007, 13:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1568
Регистрация: 18.7.2006
Где: Ivory tower

Репутация: 1
Всего: 37



Цитата

Неужели тяжело было разбить то же самое на несколько строчек? 


 Кста, при разбиении все работает корректно.  smile 
Код

x ^= y;
y ^= x;
x ^= y;



kurzon, посмотри что в MSIL получается
PM MAIL ICQ   Вверх
tol05
Дата 20.9.2007, 14:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



а что удивляться? Строка
Код

x ^= y ^= x ^= y;

это не 
Код

x ^= y;
y ^= x;
x ^= y;

это
Код

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

т.е. , если в числах, 
x = 1984 ^(2001^(1984^2001));
или
x = 1984 ^ 1984;

 smile 


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
Sartorius
Дата 20.9.2007, 14:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1568
Регистрация: 18.7.2006
Где: Ivory tower

Репутация: 1
Всего: 37



tol05, 
Код

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

 Это почему? Посмотри хотя бы на то, что в приведенном тобой выражении значение y не меняется.  smile  (А на самом деле это происходит)
PM MAIL ICQ   Вверх
Freak_FB
Дата 20.9.2007, 15:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ктулхувед
**


Профиль
Группа: Участник
Сообщений: 296
Регистрация: 13.10.2006

Репутация: 1
Всего: 4



Известен метод обмена значениями двух переменных. Но работало это в C++, компилятор которого трактует такой бред иначе, чем компилятор C#.
Код

int main(int argc, char* argv[])
{
    int x = 1985;
    int y = 2007;
    printf("x=%d, y=%d\n", x, y);
    x ^= y ^= x ^= y;
    printf("After replacement: x=%d, y=%d\n", x, y);
    return 0;
}

Код

x=1985, y=2007
After replacement: x=2007, y=1985




--------------------
user posted image
user posted image
Тонет Ктулху, все медведы горят в огне.
Я Креведко, очень страшно сегодня мне.

PM MAIL ICQ Skype GTalk Jabber   Вверх
W4FhLF
Дата 20.9.2007, 15:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


Профиль
Группа: Участник Клуба
Сообщений: 2831
Регистрация: 2.12.2006

Репутация: нет
Всего: 121



Ага, этот метод когда-то популяризировал Крис Касперски в журнале Хакер, вот и подхватили, хотя я в нём никаких достоинств не вижу. 


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
Sartorius
Дата 20.9.2007, 16:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1568
Регистрация: 18.7.2006
Где: Ivory tower

Репутация: 1
Всего: 37



Код

        int x = 1984; // (0x7c0)
00000000  push        ebp  
00000001  mov         ebp,esp 
00000003  sub         esp,18h 
00000006  push        edi  
00000007  push        esi  
00000008  push        ebx  
00000009  mov         dword ptr [ebp-4],ecx 
0000000c  xor         edi,edi 
0000000e  xor         ebx,ebx 
00000010  mov         dword ptr [ebp-10h],0 
00000017  mov         edi,7C0h 
        int y = 2001; // (0x7d1)
0000001c  mov         ebx,7D1h  // <--------- в edi помещен x в еbx - y
        x ^= y ^= x ^= y;
00000021  mov         esi,edi  // зачем то сохраняем х в еsi
00000023  xor         edi,ebx 
00000025  xor         ebx,edi // теперь в ebx(y) старое значение X
00000027  xor         esi,ebx  // обнуляем esi
00000029  mov         edi,esi //и сохраняем это в х
        x ^= y;                                   // <------- Здесь все очевидно и предсказуемо
0000002b  xor         edi,ebx  
        y ^= x;
0000002d  xor         ebx,edi 
        x ^= y;
0000002f  xor         edi,ebx 
        Console.WriteLine("x = " + x + "; y = " + y);


видно что компилятор сохраняет первоночальное значени x и когда дело доходит до последнего (левого) ^= использует его. А в y - уже старое значение x. Вот и 0

ЗЫ еще один пример того, что короткая запись совсем не обязательно лучшая 
PM MAIL ICQ   Вверх
tol05
Дата 20.9.2007, 18:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



я проверил еще раз все, что написал. Все верно. Но что значит "приведенном тобой выражении значение y не меняется"? 
Просто пример я упростил до такого вида. Мог бы написать
у = y^(x ^ y)
x = x ^у
тогда бы у менялась?  smile 

дела это не меняет и лезть в скомпилированный код ради этого не нужно. Операции имеют приоритет и порядок выполнения (слева-направо или справа-налево). В данном случае результат объясним, а каким образом, через x или через y .... Результат все равно не изменит

 smile 



--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
ivashkanet
Дата 20.9.2007, 19:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 47
Всего: 149



Цитата(tol05 @  20.9.2007,  18:56 Найти цитируемый пост)
дела это не меняет и лезть в скомпилированный код ради этого не нужно

Все нужно. 
Ассемблер показывает, что значения x и y подставляются перед выполнением строки. Т.е. в последней операции вместо y берется его первоначальное значение (2001), а не полученное в результате предыдущих преобразований (1984). Вот и получается 1984^1984 = 0

Короче, это неопределённое поведение, типа как значение выражения ++i + ++i (http://forum.vingrad.ru/index.php?show_type=forum&showtopic=150528)
PM MAIL WWW ICQ   Вверх
kurzon
Дата 20.9.2007, 19:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 307
Регистрация: 12.8.2007

Репутация: -8
Всего: -11



Код

1984^1984 = 0

Ето побитное додавание, пачему другой результат, если побитно додавать то результат будет такойже как и по обычном додавать...

Добавлено через 7 минут и 49 секунд
Код

 int x = 2001; // (0x7c0)
 int y = 2001; // (0x7d1)
  x ^=y;
  Console.WriteLine("x = " + x + "; y = " + y);
  Console.ReadLine();

Пачему x=0
Но никак не пойму, обяснить?
Я думал по механизму етому x=x+y;
PM MAIL   Вверх
tol05
Дата 20.9.2007, 20:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



Цитата(kurzon @  20.9.2007,  19:45 Найти цитируемый пост)
Ето побитное додавание, пачему другой результат, если побитно додавать то результат будет такойже как и по обычном додавать...

это поразрядное исключающее или. Ставит единицы в разрядах, который не совпадают. А если два числа совпадают, то в результате одни нули.

Цитата(ivashkanet @  20.9.2007,  19:15 Найти цитируемый пост)
Ассемблер показывает, что значения x и y подставляются перед выполнением строки. Т.е. в последней операции вместо y берется его первоначальное значение (2001), а не полученное в результате предыдущих преобразований (1984). Вот и получается 1984^1984 = 0

по приведенному ассемблеру я вижу другое... Но спорить не хочу. Не люблю длинных топиков

x = 1984 ^(2001^(1984^2001));
давайте сверим это с ассемблером (как принято выражаться "любезно предоставленным нам Sartorius")  smile

00000017  mov         edi,7C0h // в edi помещенo 1984
        int y = 2001; // (0x7d1)
0000001c  mov         ebx,7D1h  //в edi помещен x, в еbx - y (в еbx помещено 2001)
        x ^= y ^= x ^= y;
00000021  mov       esi,edi  // зачем-то сохраняем х в еsi
00000023  xor        edi,ebx // в edi помещенo 1984^2001 это 17
00000025  xor        ebx,edi // теперь в ebx(y) старое значение X нет (edi изменен) помещаем в ebx 2001^17 это 1984
00000027  xor         esi,ebx  // обнуляем esiнет (ebx изменен) помещаем в esi 1984^1984 это 0!!! 
//первый 1984 - это старый х, а второй 1984 - результат предыдущей строки

00000029  mov         edi,esi //и сохраняем это в х (0 помещаем в x)

ну дальше рассмотрен вариант Sartorius,  тут действительно все ясно smile

что скажете?

Это сообщение отредактировал(а) tol05 - 20.9.2007, 21:26


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
ivashkanet
Дата 21.9.2007, 09:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 47
Всего: 149



Цитата(ivashkanet @  20.9.2007,  19:15 Найти цитируемый пост)
последней операции вместо y берется его первоначальное значение (2001),

Я тут ошибся. Дело в x-е.
При подходе к последнему выражению (самому внешнему) x изменился (стал 2001), но используется его изначальное значение (1994)...

В подтверждении моих слов следующий код отрабатывает корректно:
Код

            y ^= x ^= y;
            x ^= y;

А все из-за того, что в двухстрочном варианте в качестве х берётся его новое значение, а не старое как в однострочном...

Добавлено @ 09:33
Цитата(Sartorius @  20.9.2007,  16:07 Найти цитируемый пост)

x ^= y ^= x ^= y;
00000021  mov         esi,edi  // зачем то сохраняем х в еsi
00000023  xor         edi,ebx 
00000025  xor         ebx,edi // теперь в ebx(y) старое значение X
00000027  xor         esi,ebx  // обнуляем esi
00000029  mov         edi,esi //и сохраняем это в х

Строки 27 и 29 показывают, что комп достаёт ранее сохранённое в esi значение, производит над ним xor со значением y и сохраняет в x (edi)

Это сообщение отредактировал(а) ivashkanet - 21.9.2007, 09:33
PM MAIL WWW ICQ   Вверх
kurzon
Дата 21.9.2007, 19:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 307
Регистрация: 12.8.2007

Репутация: -8
Всего: -11



А как переколировать в асемблер?
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0583 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.