Что делает (x ^ 0x1)!= 0 означает?

я наткнулся на следующий фрагмент кода

if( 0 != ( x ^ 0x1 ) )
     encode( x, m );

Что значит x ^ 0x1 в смысле? Это стандартный метод?

17 ответов


операция XOR (x ^ 0x1) инвертирует бит 0. Таким образом, выражение фактически означает: если бит 0 x равен 0 или любой другой бит x равен 1, то выражение истинно.

и наоборот, выражение false, если x == 1.

таким образом, тест такой же, как:

if (x != 1)

и поэтому (возможно) излишне запутан.


  • ^ - это побитовое XOR операция
  • 0x1 и 1 в hex-нотации
  • x ^ 0x1 перевернет последний бит x (обратитесь к таблице истинности XOR в ссылке выше, если это вам не ясно).

таким образом, условие (0 != ( x ^ 0x1 )) будет true, если x больше 1 или если последний бит x равен 0. Что оставляет только x==1 Как значение, при котором условие будет ложным. Так это эквивалентно

if (x != 1)

P. S. адский способ реализовать такое простое условие, я мог бы добавить. Не делай этого. И если вы должны написать сложный код,оставить комментарий. Умоляю вас.


это может показаться упрощенным объяснением, но если кто-то хочет пройти через него медленно, это ниже:

^ - это побитовое XOR оператор в C, C++ и C#.

побитовый XOR принимает два битовых шаблона одинаковой длины и выполняет логическое исключение или операция для каждой пары соответствующих битов.

Exclusive или логическая операция, которая выводит true всякий раз, когда оба входы отличаются (правда, в другое ложно).

на таблица истинности of a xor b:

a           b        a xor b
----------------------------
1           1           0
1           0           1
0           1           1
0           0           0

Итак, давайте проиллюстрируем 0 == ( x ^ 0x1 ) выражение на уровне двоичного кода:

             what? xxxxxxxx (8 bits)
               xor 00000001 (hex 0x1 or 0x01, decimal 1)    
             gives 00000000
---------------------------
the only answer is 00000001

так:

   0 == ( x ^ 0x1 )    =>    x == 1
   0 != ( x ^ 0x1 )    =>    x != 1

это оператор exclusive или (XOR). Чтобы понять, как это работает, вы можете запустить этот простой код

    std::cout << "0x0 ^ 0x0 = " << ( 0x0 ^ 0x0 ) << std::endl;
    std::cout << "0x0 ^ 0x1 = " << ( 0x0 ^ 0x1 ) << std::endl;
    std::cout << "0x1 ^ 0x0 = " << ( 0x1 ^ 0x0 ) << std::endl;
    std::cout << "0x1 ^ 0x1 = " << ( 0x1 ^ 0x1 ) << std::endl;

выход будет

0x0 ^ 0x0 = 0
0x0 ^ 0x1 = 1
0x1 ^ 0x0 = 1
0x1 ^ 0x1 = 0

так это выражение

0 != ( x ^ 0x1 )

будет равно true только тогда, когда x != 0х1.

он не изменяет сам X. Он проверяет только, равен ли x 0 или 1. это rxpression может быть изменено на

if ( x != 0x1 )

он проверяет, что x на самом деле не 0x1... xoring x с 0x1 приведет к 0, только если x is 0x1 ... это старый трюк, в основном используемый в ассемблере


на ^ оператор побитовый xor. И 0x1 число 1, записывается как шестнадцатеричная константа.

и x ^ 0x1 вычисляет новое значение, которое совпадает с x, но с наименее значительным битом перевернутым.

код не делает ничего, кроме сравнения x с 1, очень запутанным и неясным образом.


оператор xor (exclusive or) чаще всего используется для инвертирования одного или нескольких битов. Операция заключается в том, чтобы спросить, является ли один из битов одним, это приводит к следующей таблице истинности (A и B-входы, Y-выход):

A    B    Y
0    0    0
0    1    1
1    0    1
1    1    0

теперь цель этого кода, похоже, состоит в том, чтобы проверить, является ли последний бит 1, а остальные-0, это равно if ( x != 1 ). Причиной этого неясного метода может быть то, что использовались и, возможно, используются предыдущие методы обработки битов другие места в программе.


^ - побитовое xor operator на c. В вашем случае x равно 1. например x имеет значение 10, то 10d ^ 1d ===> 1010b ^ 0001b = 1011b, 1011b == 11d таким образом, условие становится истинным.


побитовый тест кажется преднамеренной путаницей, но если базовые данные являются корпоративными данными из мэйнфреймовой системы IBM, это может быть просто код, написанный, чтобы отразить исходную документацию. Форматы данных IBM восходят к 1960-м годам и часто кодируют флаги как отдельные биты в word для сохранения хранилища. По мере изменения форматов байты флагов добавлялись в конце существующих записей для обеспечения обратной совместимости. Документация для записи SMF, например, может отображаться код языка ассемблера для проверки трех отдельных битов в трех разных словах в одной записи, чтобы решить, что данные являются входным файлом. Я знаю гораздо меньше о внутренних TCP/IP, но вы также можете найти там битовые флаги.


оператор ^ является побитовым-xor (см. &, | ). Результат для битовой пары:

0 ^ 0 == 0
0 ^ 1 == 1
1 ^ 0 == 1
1 ^ 1 == 0

поэтому выражение,

( x ^ 0x1 )

инвертирует / переворачивает 0-й бит x (оставляя другие биты неизменными).

рассмотрим, может ли x иметь значения помимо 0x0 и 0x1? Когда x-одно битовое поле, оно может иметь только значения 0x0 и 0x1, но когда x-int (char/short/long/etc), биты, кроме bit0, могут влиять на результат выражения.

в данное выражение позволяет битам рядом с bit0 влиять на результат,

if ( 0 != ( x ^ 0x1 ) )

который имеет эквивалентную правдивость, как это (более простое) выражение,

if ( x ^ 0x1 )

обратите внимание, что это выражение будет рассматривать только bit0,

if( 0x1 & ( x ^ 0x1 ) )

таким образом, представленное выражение действительно объединяет две проверки выражений,

if( ( x & ~0x1 )  //look at all bits besides bit0
||  ( x ^ 0x1 ) ) //combine with the xor expression for bit0

намеревался ли автор только проверить bit0 и намеревался использовать это выражение,

if( 0x1 & ( x ^ 0x1 ) )

или автор намеревался comingle значения для bit1-bitN и xor для bit0?


я добавляю новый ответ, потому что никто не объяснил, как получить ответ интуитивно.

инверсия + is -.
Обратный ^ и ^.

как вы решаете 0 != x - 1 на x? Вы + 1 для обеих сторон: 0 + 1 != x - 1 + 11 != x.
Как вы решаете 0 != x ^ 1 на x? Вы ^ 1 для обеих сторон: 0 ^ 1 != x ^ 1 ^ 11 != x.


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

как-то декодер должен быть в состоянии сделать вывод, что эти ценности отсутствуют. Если они находятся в конце некоторой структуры, это может быть передано через length значение, которое всегда присутствует.


XOR полезен в перечислении флагов C#. Чтобы удалить один флаг из значения перечисления, необходимо использовать оператор xor (ссылка здесь)

пример:

[Flags]
enum FlagTest { None 0x0, Test1 0x1, Test2 0x2, Test3 0x4}

FlagTest test = FlagTest.Test2 | FlagTest.Test3;
Console.WriteLine(test); //Out: FlagTest.Test2 | FlagTest.Test3
test = test ^ FlagTest.Test2;
Console.WriteLine(test); //Out: FlagTest.Test3

есть много хороших ответов, но мне нравится думать об этом более простым способом.

if ( 0 != ( x ^ 0x1 ) );

прежде всего. Оператор if является ложным, только если аргумент равен нулю. Это означает, что сравнивать не равное нулю бессмысленно.

if ( a != 0 );
// Same as
if ( a );

Итак, это оставляет нас с:

if ( x ^ 0x1 );

XOR с одним. То, что делает XOR, по существу найти битов, которые отличаются. Итак, если все биты одинаковы, он вернет 0. Поскольку 0-это ложь, только время, когда он вернет false, если все биты одинаковы. Поэтому он будет ложным, если аргументы одинаковы, истинным, если они разные...так же, как не равно оператора.

if ( x != 0x1 );

если факт, единственное различие между ними заключается в том, что != возвращает 0 или 1, в то время как ^ вернет любое число, но truthyness результат всегда будет одинаковым. Об этом легко думать.

(b != c) === !!(b ^ c) // for all b and c

в окончательное "Упрощение" - это преобразование 0x1 до десятичного знака, который равен 1. Поэтому ваше утверждение эквивалентно:

if ( x != 1 )

^ является побитовое XOR оператор

Если x = 1

          00000001   (x)       (decimal 1)
          00000001   (0x1)     (decimal 1)
XOR       00000000   (0x0)     (decimal 0)

здесь 0 = = (x ^ 0x1 )

Если x = 0

          00000000   (x)       (decimal 0)
          00000001   (0x1)     (decimal 1)
XOR       00000001   (0x1)     (decimal 0)

здесь 0 != (x ^ 0x1 )

таблица истинности xor b:

a           b        a xor b
----------------------------
1           1           0
1           0           1
0           1           1
0           0           0

код просто означает


как я вижу, ответы до сих пор пропускают простое правило для обработки XORs. Не вдаваясь в подробности, что ^ и 0x mean (и if и != etc), выражение 0 != (x^1) можно переработать следующим образом, используя тот факт, что (a^a)==0:

0 != (x^1) <=> [xor left and right side by 1]
(0^1) != (x^1^1) <=>
1 != x

стандартная техника, что может здесь используется, чтобы повторить идиому, как она появляется в окружающем контексте для ясности, а не запутать ее, заменив ее идиомой, которая арифметически проще, но контекстуально бессмысленна.

окружающий код может часто ссылаться на (x ^ 1), или тест может спросить: "если бы бит 0 был наоборот, эта битовая маска была бы пустой?".

учитывая, что условие вызывает что-то будет encode()ed, возможно, в контексте состояние по умолчанию бита 0 было инвертировано другими факторами, и нам нужно только кодировать дополнительную информацию, если какой-либо из битов отклоняется от их значения по умолчанию (обычно все-ноль).

Если вы берете выражение из контекста и спрашиваете, что оно делает, вы упускаете основное намерение. Вы можете просто посмотреть на выходные данные сборки компилятора и увидеть, что он просто выполняет прямое сравнение равенства с 1.