문제

C++에서 "bool" 값에 대해 비트 연산자 &, | 및 ^를 사용하지 않는 이유가 있나요?

가끔 두 조건 중 하나만이 참(XOR)이 되기를 원하는 상황이 발생하기 때문에 조건식에 ^ 연산자를 넣기만 하면 됩니다.또한 때로는 결과가 참인지 아닌지(단락하는 대신) 조건의 모든 부분을 평가하기를 원하므로 & 및 |를 사용합니다.또한 때때로 부울 값을 축적해야 하는데 &= 및 |=가 매우 유용할 수 있습니다.

이 작업을 수행하면서 눈썹이 몇 번 치켜올랐지만, 코드는 그렇지 않은 경우보다 여전히 의미 있고 깔끔합니다.bool에 이것을 사용하지 않을 이유가 있습니까?이에 대해 나쁜 결과를 제공하는 최신 컴파일러가 있습니까?

도움이 되었습니까?

해결책

|| 그리고 && 부울 연산자이고 내장된 연산자는 다음 중 하나를 반환하도록 보장됩니다. true 또는 false.다른 것은 없습니다.

|, & 그리고 ^ 비트 연산자입니다.작업하는 숫자의 영역이 1과 0이면 정확히 동일하지만 C 언어의 경우와 같이 부울 값이 엄격하게 1과 0이 아닌 경우에는 일부 동작이 발생할 수 있습니다. 당신은 원하지 않았습니다.예를 들어:

BOOL two = 2;
BOOL one = 1;
BOOL and = two & one;   //and = 0
BOOL cand = two && one; //cand = 1

그러나 C++에서는 bool 유형은 다음 중 하나여야 합니다. true 또는 false (암묵적으로 각각 다음으로 변환됩니다. 1 그리고 0), 따라서 이 입장에서는 걱정이 덜하지만, 사람들이 코드에서 그러한 것을 보는 데 익숙하지 않다는 사실은 그렇게 하지 않는 것에 대한 좋은 논거가 됩니다.그냥 말해 b = b && x 그리고 끝내세요.

다른 팁

두 가지 주요 이유.즉, 신중하게 고려하십시오.거기에는 타당한 이유가 있을 수 있지만, 부서지기 쉬울 수 있고 스스로 말했듯이 사람들은 일반적으로 이와 같은 코드를 보는 데 익숙하지 않기 때문에 귀하의 의견에 매우 명시적인 경우.

비트별 xor != 논리 xor(0과 1 제외)

첫째, 이외의 값으로 작업하는 경우 false 그리고 true (또는 0 그리고 1, 정수로), ^ 연산자는 논리적 xor와 동일하지 않은 동작을 도입할 수 있습니다.예를 들어:

int one = 1;
int two = 2;

// bitwise xor
if (one ^ two)
{
  // executes because expression = 3 and any non-zero integer evaluates to true
}

// logical xor; more correctly would be coded as
//   if (bool(one) != bool(two))
// but spelled out to be explicit in the context of the problem
if ((one && !two) || (!one && two))
{
  // does not execute b/c expression = ((true && false) || (false && true))
  // which evaluates to false
}

이를 먼저 표현한 사용자 @Patrick에게 감사드립니다.

작업 순서

두번째, |, &, 그리고 ^, 비트 연산자로서 단락하지 마십시오.또한 단일 명령문에 함께 연결된 여러 비트 연산자는 명시적 괄호가 있어도 컴파일러를 최적화하여 재정렬할 수 있습니다. 왜냐하면 3개 연산은 모두 일반적으로 교환 가능하기 때문입니다.작업 순서가 중요한 경우 이는 중요합니다.

다시 말해서

bool result = true;
result = result && a() && b();
// will not call a() if result false, will not call b() if result or a() false

항상 동일한 결과(또는 최종 상태)를 제공하지는 않습니다.

bool result = true;
result &= (a() & b());
// a() and b() both will be called, but not necessarily in that order in an
// optimizing compiler

메소드를 제어할 수 없기 때문에 이는 특히 중요합니다. a() 그리고 b(), 또는 다른 사람이 나중에 종속성을 이해하지 못한 채 변경하여 불쾌한(종종 릴리스 빌드에만 해당) 버그를 일으킬 수 있습니다.

제 생각에는

a != b

당신이 원하는 것입니다

치켜뜬 눈썹은 그 일을 그만둘 만큼 충분히 말해야 합니다.컴파일러용 코드를 작성하는 것이 아니라 먼저 동료 프로그래머를 위해 작성한 다음 컴파일러용으로 작성합니다.컴파일러가 작동하더라도 다른 사람을 놀라게 하는 것은 원하는 것이 아닙니다. 비트 연산자는 bool이 아닌 비트 연산을 위한 것입니다.
포크로 사과도 먹나요?효과가 있지만 사람들을 놀라게 하므로 하지 않는 것이 좋습니다.

비트레벨 연산자의 단점.

물어:

“비트 연산자를 사용하지 않을 이유가 있나요? &, |, 그리고 ^ C++의 "bool" 값은 무엇입니까?”

예, 논리 연산자, 이는 내장된 고급 부울 연산자입니다. !, && 그리고 ||, 다음과 같은 이점을 제공합니다.

  • 보장 인수 변환 에게 bool, 즉.에게 0 그리고 1 서수 값.

  • 보장 단락 평가 여기서 표현식 평가는 최종 결과가 알려지자마자 중지됩니다.
    이는 트리-값 논리로 해석될 수 있습니다. 진실, 거짓 그리고 불확정.

  • 읽을 수 있는 동등한 텍스트 not, and 그리고 or, 내가 직접 사용하지 않더라도.
    독자 Antimony가 주석에서 언급했듯이 비트 레벨 연산자에는 대체 토큰이 있습니다. bitand, bitor, xor 그리고 compl, 그러나 내 생각에는 이것들이 다음보다 읽기가 쉽지 않습니다. and, or 그리고 not.

간단히 말해서, 상위 수준 연산자의 이러한 장점은 비트 수준 연산자의 단점입니다.

특히 비트 연산자에는 0/1로의 인수 변환이 없기 때문에 다음과 같은 결과가 나옵니다. 1 & 20, 하는 동안 1 && 2true.또한 ^, 비트 배타적 또는 이 방식으로 오작동할 수 있습니다.부울 값으로 간주되는 1과 2는 동일합니다. true, 그러나 비트 패턴으로 간주되는 것은 다릅니다.


논리적으로 표현하는 방법 하나 또는 C++에서.

그런 다음 질문에 대한 약간의 배경 지식을 제공합니다.

"때때로 두 조건 중 하나만이 true(XOR)가 되기를 원하는 상황이 발생하기 때문에 조건식에 ^ 연산자를 넣기만 하면 됩니다."

음, 비트 연산자는 더 높은 우선순위 논리 연산자보다이는 특히 다음과 같은 혼합 표현에서 다음을 의미합니다.

a && b ^ c

아마도 예상치 못한 결과를 얻게 될 것입니다 a && (b ^ c).

대신 그냥 쓰세요

(a && b) != c

당신이 의미하는 바를 더 간결하게 표현하십시오.

다중 인수의 경우 하나 또는 해당 작업을 수행하는 C++ 연산자는 없습니다.예를 들어, 다음과 같이 쓴다면 a ^ b ^ c 그보다 "어느 쪽이든"이라는 표현은 아닙니다. a, b 또는 c 사실이다".대신에 “홀수 개의 숫자가 있습니다. a, b 그리고 c 사실입니다', 이는 그 중 하나일 수도 있고 3개 모두일 수도 있습니다…

일반적인 which/or when을 표현하기 위해 a, b 그리고 c 유형이다 bool, 그냥 써

(a + b + c) == 1

또는bool 인수를 다음으로 변환합니다. bool:

(!!a + !!b + !!c) == 1


사용 &= 부울 결과를 축적합니다.

더 자세히 설명해주시는데,

“때때로 부울 값을 축적해야 할 때도 있습니다. &= 그리고 |=? 꽤 유용할 수 있어요.”

글쎄요, 이는 각각의 여부를 확인하는 것과 같습니다. 모두 또는 어느 조건이 만족되고, 드 모건의 법칙 한 곳에서 다른 곳으로 가는 방법을 알려줍니다.즉.그 중 하나만 필요합니다.원칙적으로 사용할 수 있습니다 *= 로서 &&=-연산자(오래된 George Boole이 발견한 것처럼 논리 AND는 매우 쉽게 곱셈으로 표현될 수 있음) 그러나 이는 코드 관리자를 당황하게 하고 아마도 오해를 불러일으킬 수 있다고 생각합니다.

다음 사항도 고려하세요.

struct Bool
{
    bool    value;

    void operator&=( bool const v ) { value = value && v; }
    operator bool() const { return value; }
};

#include <iostream>

int main()
{
    using namespace std;

    Bool a  = {true};
    a &= true || false;
    a &= 1234;
    cout << boolalpha << a << endl;

    bool b = {true};
    b &= true || false;
    b &= 1234;
    cout << boolalpha << b << endl;
}

Visual C++ 11.0 및 g++ 4.7.1을 사용한 출력:

true
false

결과에 차이가 나는 이유는 비트레벨 때문입니다. &= 로의 변환을 제공하지 않습니다. bool 오른쪽 인수 중 하나입니다.

그렇다면 다음 중 어떤 결과를 사용하고 싶나요? &=?

전자의 경우, true, 그런 다음 연산자를 더 잘 정의합니다(예:위와 같음) 또는 명명된 함수를 사용하거나 오른쪽 표현식의 명시적 변환을 사용하거나 전체 업데이트를 작성합니다.

Patrick의 답변과는 달리 C++에는 ^^ 단락 배타적 논리합을 수행하는 연산자입니다.잠시 생각해 보면, ^^ 어쨌든 연산자는 의미가 없습니다.배타적 OR를 사용하면 결과는 항상 두 피연산자 모두에 따라 달라집니다.그러나 Patrick은 다음과 같은 사항에 대해 경고했습니다.bool "부울" 유형은 비교할 때 동일하게 유지됩니다. 1 & 2 에게 1 && 2.이에 대한 전형적인 예는 Windows입니다. GetMessage() 3상태를 반환하는 함수 BOOL:0이 아닌, 0, 또는 -1.

사용 & 대신에 && 그리고 | 대신에 || 이는 드문 오타가 아니므로 고의로 오타를 낸 경우에는 그 이유를 설명할 가치가 있습니다.

패트릭은 좋은 점을 지적했고 나는 그 점을 반복하지 않을 것입니다.그러나 가능한 한 잘 명명된 부울 변수를 사용하여 'if' 문을 영어로 읽을 수 있도록 줄이는 것이 좋습니다. 예를 들어 이것은 부울 연산자를 사용하지만 비트 단위를 동일하게 사용하고 부울의 이름을 적절하게 지정할 수 있습니다.

bool onlyAIsTrue = (a && !b); // you could use bitwise XOR here
bool onlyBIsTrue = (b && !a); // and not need this second line
if (onlyAIsTrue || onlyBIsTrue)
{
 .. stuff ..
}

부울을 사용하는 것이 불필요해 보인다고 생각할 수도 있지만 두 가지 주요 사항에 도움이 됩니다.

  • 'if' 조건에 대한 중간 부울이 조건의 의도를 더 명확하게 만들기 때문에 코드를 더 쉽게 이해할 수 있습니다.
  • 부울 값에 대한 비트 연산자와 같이 비표준 코드나 예상치 못한 코드를 사용하는 경우 사람들은 왜 그렇게 했는지 훨씬 더 쉽게 알 수 있습니다.

편집하다:'if' 문에 대한 조건문을 원한다고 명시적으로 말하지 않으셨는데(비록 그럴 가능성이 가장 높지만) 그게 제 가정이었습니다.그러나 중간 부울 값에 대한 나의 제안은 여전히 ​​유효합니다.

IIRC, 많은 C++ 컴파일러는 비트 연산의 결과를 부울로 변환하려고 시도할 때 경고합니다.컴파일러를 만족시키려면 유형 캐스트를 사용해야 합니다.

if 표현식에서 비트 연산을 사용하면 동일한 비판을 받을 수 있지만 아마도 컴파일러에서는 그렇지 않을 것입니다.0이 아닌 모든 값은 참으로 간주되므로 "if (7 & 3)"과 같은 내용이 참이 됩니다.이 동작은 Perl에서는 허용될 수 있지만 C/C++는 매우 명시적인 언어입니다.스팍의 눈썹은 실사라고 생각합니다.:) 귀하의 목표가 무엇인지 완벽하게 명확하게 하기 위해 "== 0" 또는 "!= 0"을 추가하겠습니다.

하지만 어디까지나 개인적인 취향인 것 같습니다.Lint나 유사한 도구를 통해 코드를 실행하고 그것이 현명하지 못한 전략이라고 생각하는지 확인합니다.개인적으로는 코딩 실수처럼 보입니다.

bool에 대한 비트 연산을 사용하면 논리 연산에 의해 가져온 'cmp' 명령으로 인해 프로세서에 의한 불필요한 분기 예측 논리를 절약하는 데 도움이 됩니다.

논리 연산을 비트 연산(모든 피연산자가 bool인 경우)으로 바꾸면 동일한 결과를 제공하는 보다 효율적인 코드가 생성됩니다.이상적으로 효율성은 논리 연산을 사용하여 순서 지정에 활용될 수 있는 모든 단락 이점보다 커야 합니다.

프로그래머가 왜 그렇게 했는지 이유를 설명해야 하지만 이로 인해 코드를 약간 읽기 어렵게 만들 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top