(x ^ 0x1)! = 0 무엇을 의미합니까?


183

다음 코드 스 니펫을 발견했습니다.

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

무슨 x ^ 0x1뜻입니까? 이것이 표준 기술입니까?


97
코드 난독 화 는 매우 표준입니다.
raina77ow

47
이것은 "정상적인"방정식과 같은 접근 방식으로 해결할 수 있습니다. 0 != (x ^ 1)→ x 또는 양변을 1 → (0 ^ 1) != (x ^ 1 ^ 1)→ 단순화 →1 != x
Score_Under

4
어떻게 if (1 != x)작성하기 어려운지 모르겠습니다 .
Adriano Varoli Piazza

12
@Spook이 처음으로 다양한 의견은 typeof x가 주어지지 않았 음을 분명히 지적합니다. 따라서이 C ++ 태그가 지정된 문제의 정수인지 알 수 없습니다. 물론 이것이 C이거나 x정수이면 답은 쉽지만 주어진 것이 아니며 과부하 가능성이 operator ^존재합니다.
chux-복원 Monica Monica

11
나는 ...이 많은 upvotes를 얻을 표시되지 않습니다
laike9m

답변:


277

XOR 연산 ( x ^ 0x1)은 비트 0을 반전시킵니다. 따라서이 표현은 x의 비트 0이 0이거나 x의 다른 비트가 1이면 표현식이 참임을 의미합니다.

반대로 x == 1이면 표현식이 false입니다.

따라서 테스트는 다음과 같습니다.

if (x != 1)

그러므로 (논쟁 적으로) 불필요하게 난독 화된다.


39
이봐, 당신은 상황을 모른다. x가 일종의 비트 플래그 인 경우! = 연산자를 사용하는 것보다 실제로 쓰기가 더 명확합니다.
Spook

40
@Spook : 단일 비트 플래그를 테스트하는 것이 아니라 x의 전체 너비를 테스트합니다. 단일 비트를 테스트하려는 경우 비트 AND를 사용하는 등의 명확한 관용구가 있습니다.
Paul R

115
불필요하게 혼란스러워? 코드를 난독 처리하는 것이 우리의 일이라는 것을 모르십니까? 우리가 누구나 이해할 수있는 간단한 코드를 썼다면, 왜 세상에서 우리 위치의 종교적 신성이 어디로 갈 것입니까? 우리는 갑자기 다른 사람들처럼 평범한 일꾼이되었습니다. 난독 화는 본질적으로 필요합니다.
Thom

31
실제로 Spook이 옳습니다. 테스트 (x! = 1)는 동일하지 않습니다. 코드는 C ++ 일 수 있으며 C ++에서 ^는 모든 작업을 수행하는 연산자 일 수 있습니다. 따라서 컨텍스트를 모릅니다. @Spook이 옳습니다.
xryl669

82
@TheThom уєт уσυ ωяιтє ιи ¢ ℓєαя тєχт
bobobobo

78
  • ^비트 XOR 연산입니다
  • 0x1이다 1진수 표기법으로
  • x ^ 0x1의 마지막 비트를 뒤집습니다 x(확실하지 않은 경우 위 링크의 XOR 진리표 참조).

따라서 조건 (0 != ( x ^ 0x1 ))x1보다 크거나 마지막 비트 x가 0 이면 조건 이 참 이됩니다. 조건이 거짓이 될 값으로 x == 1 만 남습니다. 따라서

if (x != 1)

PS Hell은 그러한 간단한 조건을 구현하는 방법을 추가 할 수 있습니다. 하지마 복잡한 코드를 작성해야하는 경우 주석을 남기십시오 . 당신을 간청합니다.


7
아니다 x==0; 4 ^ 0x1사실이지만 4==0분명히 거짓입니다.
Fred Foo

4
"조건이"인 것 같습니다. if (x == 0)같지 x != 1않습니까?
Andrew-Dufresne

6
동등성 x은 필수 유형 인 것을 전제로합니다 . 그것이 float또는 double인 경우, 표현이 true를 얻을 것이라고 믿습니다 1.0 <= x < 2.0. 그리고 x사용자 정의 유형 인 경우 x유고, 캥거루, 유명한 작곡가의 생일 또는 중국의 현재 달러 표시 차 가격과 최소 3 자리 숫자를 공유하는 숫자 이면 표현식이 true를 리턴 할 수 있습니다.
supercat

4
@supercat 전혀 없다 operator^위해 float/ double.
솜털

1
@supercat : 부동 소수점에서 정수로의 변환이 필요한 경우 변환은 암시 적입니다 (캐스트 구문이 필요하지 않음). 그러나 비트 연산자는 변환을 트리거하지 않으며 부동 소수점 유형에서는 실패합니다.
Ben Voigt

49

이것은 지나치게 단순화 된 설명처럼 보이지만, 누군가가 천천히 살펴보고 싶다면 아래에 있습니다.

^c, c ++ 및 c # 의 비트 XOR 연산자입니다.

비트 XOR은 길이가 같은 두 개의 비트 패턴을 사용하여 각 해당 비트 쌍에 대해 논리 배타적 OR 연산을 수행합니다.

배타적 OR은 두 입력이 다를 때마다 true를 출력하는 논리 연산입니다 (하나는 true, 다른 하나는 false).

진리표의 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

34

배타적 OR (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 )

x! = 0x1 일 때만 참이됩니다.

x 자체는 변경되지 않습니다. x가 0인지 1인지 만 확인합니다.이 rxpression은

if ( x != 0x1 )

19

그것은 검사 x실제로되지 0x1... xor보내고 x함께 0x1하면 0으로됩니다 만 x입니다 0x1...이 대부분 어셈블리 언어로 사용하는 오래 된 트릭


이보다 빠릅 != 1니까?
Fiddling Bits

2
고대에는 수동 어셈블리 최적화 (x86)를 수행하는 동안 올바르게 xor접근하면 기계 코드가 적었고 해당 할당보다 빠르게 실행되었습니다 0...하지만이 질문에는 xorAND 비교 가 포함되어 !=있으므로 빨리. 그러나 확실하지는 않지만 일부 컴파일러 생성 어셈블리를 볼 필요가 있습니다.
Ferenc Deak

10
@BitFiddlingCodeMonkey : 아니요. XOR이 일부 기본 수준 평등 테스트보다 빠르면 컴파일러는 XOR을 생성하여 동등성을 테스트합니다. 따라서 XOR은 컴파일러 최적화에 대한 동등성 테스트보다 빠르지 않습니다. 빠른 코드를 작성하는 규칙 101은 "컴파일러를 시도하지 마십시오. 실제로는 느리게 읽을 수없는 코드를 작성하게됩니다."
Matt

@fritzone IIRC에서 XOR 트릭은 레지스터 저장과 관련이있었습니다. 레지스터로드는 b / c로 리터럴이 OP에서 직접 인코딩 될 수 있으며 상태 플래그와 약간의 차이점이 있습니다 (그러나 대부분의 어셈블리는 켜져있었습니다) 68k 및 DSP).
mpdonadio

1
@ MPD : 일반적으로 레지스터를 지우는 것과 관련이 있습니다 (적어도 386+ 이상). xor eax, eax 는 2 바이트에서 eax를 0으로 설정하지만 mov eax, 0 은 3 또는 6 바이트 (인코딩에 따라 다름)를 사용하며 xor 형식 보다 디코딩하는 데 약간 더 오래 걸립니다 .
Matt

18

^연산자는 비트 단위 XOR된다. 그리고 16 진수 상수로 작성된 0x1숫자 1입니다.

따라서 x ^ 0x1와 동일 x하지만 가장 중요도가 낮은 비트가 뒤집힌 새 값으로 평가됩니다 .

이 코드는 매우 복잡하고 모호한 방식으로 x와 1을 비교하는 것 이상을 수행하지 않습니다.


11

xor (배타적) 연산자는 하나 이상의 비트를 반전시키는 데 가장 일반적으로 사용됩니다. 연산은 비트 중 정확히 하나가 1인지 묻는 것입니다. 이는 다음 진리표로 이어집니다 (A 및 B는 입력, Y는 출력).

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

이제이 코드의 목적은 마지막 비트가 1이고 다른 비트가 0인지 확인하는 것 같습니다 if ( x != 1 ). 이 모호한 방법의 이유는 이전 비트 조작 기술이 사용되고 아마도 프로그램의 다른 위치에서 사용 되었기 때문일 수 있습니다.


8

^에 비트 단위 xor operator입니다 c. 귀하의 경우, X는, 예를 들어 1과 XOR 연산되고 x그 후, 값 (10)을 갖는 10d ^ 1d ===> 1010b ^ 0001b = 1011b, 1011b == 11d조건이 참이되도록.


당신의 대답에 오타. 10 != 1010
Fiddling Bits

@BitFiddlingCodeMonkey : 귀하의 의견에 오타 :10 (decimal) == 1010 (binary)
Paul R

6
@PaulR b거기에 무언가를 넣지 않으면 어떻게 소수와 이진수가 무엇인지 아는 사람은 누구 입니까?
Fiddling Bits

0b1010이 Pythonic 일을하지 않습니까?
TankorSmash

8

비트 단위 테스트는 의도적 인 난독 화처럼 보이지만 기본 데이터가 IBM 메인 프레임 시스템의 회사 데이터 인 경우 원래 문서를 반영하기 위해 코드가 작성되었을 수 있습니다. IBM 데이터 형식은 1960 년대로 거슬러 올라가서 종종 단어를 단일 비트로 플래그를 인코딩하여 스토리지를 절약합니다. 형식이 수정되면 기존 레코드 끝에 플래그 바이트가 추가되어 이전 버전과의 호환성을 유지합니다. 예를 들어, SMF 레코드에 대한 문서는 데이터가 입력 파일임을 결정하기 위해 단일 레코드에서 세 개의 다른 단어 내에서 세 개의 개별 비트를 테스트하는 어셈블리 언어 코드를 보여줄 수 있습니다. TCP / IP 내부에 대해서는 잘 모르지만 비트 플래그도 찾을 수 있습니다.


7

연산자 ^는 비트 xor입니다 (&, | 참조). 비트 페어의 결과는

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

그래서 표현은

( x ^ 0x1 )

x의 0 번째 비트를 반전 / 플랩합니다 (다른 비트는 그대로 유지).

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 ) )

아니면 제작자가 bit1-bitN과 xor의 bit0 값을 가져 오려고합니까?


7

아무도 대답을 직관적으로 얻는 방법을 실제로 설명하지 않았기 때문에 새로운 답변을 추가하고 있습니다.

의 반대는 +입니다 -.
의 반대는 ^입니다 ^.

당신은 어떻게 해결합니까 0 != x - 1위해 x? 당신 + 1은 양쪽에 : 0 + 1 != x - 1 + 11 != x.
당신은 어떻게 해결합니까 0 != x ^ 1위해 x? 당신 ^ 1은 양쪽에 : 0 ^ 1 != x ^ 1 ^ 11 != x.


6

에 다른 비트 또는 비트 필드 값 x이 있다고 생각합니다. 이는 하위 비트 만 설정되어 있는지 테스트하기위한 것입니다. 맥락에서 나는 이것이 기본값이며, 따라서 이것과 일부 관련 m(아마도 인코딩하는 데 더 비싼)의 인코딩은 기본값이거나 생성자에서 초기화되거나 유사해야하기 때문에 건너 뛸 수 있다고 생각합니다.

어떻게 든 디코더는 이러한 값이 누락되었음을 유추 할 수 있어야합니다. 그것들이 어떤 구조의 끝에 있다면, length항상 존재 하는 값을 통해 전달 될 수 있습니다 .


4

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

하지만 질문은하지의 C #, C ++에 관한 것입니다
theDmi

@theDmi : 그러나 비트 조작 및 비트 마스크에 대해서도. C #의 플래그 열거는 분명히 비트 마스크에 관한 것입니다.
그렉.

또한 C ++에서도 유용 할 수 있습니다. 스택 1스택 2
Igrek를

이 답변은 비트 XOR 연산자에 대한 토론 이외의 원래 질문과 관련이없는 것 같습니다.
Paul R

4

좋은 답변이 많이 있지만 더 간단한 방법으로 생각하고 싶습니다.

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

가장 먼저. 인수가 0 인 경우 if 문은 false입니다. 즉, 0이 아닌 비교는 의미가 없습니다.

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

그래서 우리에게 다음을 남깁니다.

if ( x ^ 0x1 );

하나의 XOR. XOR은 본질적 으로 다른 비트를 감지 합니다. 따라서 모든 비트가 동일하면 0을 반환합니다. 0이 false이므로 모든 비트가 동일한 경우에만 false를 반환합니다. 따라서 인수가 동일하면 false이고, 연산자가 같지 않은 것처럼 다른 경우 true 입니다.

if ( x != 0x1 );

사실, 둘 사이의 유일한 차이점은 !=0 또는 1 ^을 반환하고 숫자를 반환하지만 결과 의 진실성 은 항상 동일하다는 것입니다. 그것에 대해 생각하는 쉬운 방법입니다.

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

마지막 "단순화"는 0x110 진수 1 로 변환 됩니다. 따라서 명령문은 다음과 같습니다.

if ( x != 1 )

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

코드는 단순히 의미


6
또 다른 중복 답변을 게시해야합니까?
Mysticial

2
다른 답변을 말할 수는 있지만 중복 할 수는 없습니다. 마음에
든다

1

여기서 사용될 있는 표준 기술 은 명확성을 위해 주변 문맥에 나타나는 관용구를 반복하여 산술적으로 단순하지만 문맥 상 의미가없는 관용구로 대체함으로써 난독 화하는 것입니다.

주변 코드가을 자주 참조 (x ^ 1)하거나 테스트에서 "비트 0이 다른 방법 인 경우이 비트 마스크가 비어 있습니까?"라고 묻습니다.

이 조건으로 인해 무언가가 제거되는 경우 encode()컨텍스트에서 비트 0의 기본 상태가 다른 요인에 의해 반전 된 것일 수 있으며 비트 중 하나가 기본값에서 벗어난 경우 추가 정보 만 인코딩하면됩니다 (일반적으로 모든 0). ).

문맥 밖에서 표현을 취하고 그것이 무엇을하는지 묻는다면, 당신은 근본적인 의도를 간과합니다. 컴파일러의 어셈블리 출력을보고 1과 직접 동등성을 비교하는 것을 볼 수 있습니다.


0

내가 알기로 지금까지 답변은 XORs 처리에 대한 간단한 규칙을 그리워합니다 . 세부 사항으로 가지 않고 무엇을 ^하고 0x평균 (및 if, 및 !=등), 표현은 0 != (x^1)사실이를 사용하여 다음과 같이 재 작업 할 수 있습니다 (a^a)==0:

0 != (x^1) <=> [xor left and right side by 1]
(0^1) != (x^1^1) <=>
1 != x
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.