C ++에서 부울에 비트 연산자 사용
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
유형이 a true
또는 a 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
당신이 원하는 것입니다
진 눈썹은 그것을 멈출만큼 충분히 충분히 말해 줄 것입니다. 컴파일러 용 코드를 작성하는 것이 먼저 동료 프로그래머 용으로 다음 컴파일러 용으로 작성합니다. 컴파일러가 작동하는 다른 사람들을 고맙게 생각하는 것이 아닙니다. 비트 연산자는 부울이 아닌 비트 연산을위한 것입니다.
포크로 사과도 먹는 것 같아요? 작동하지만 사람들을 놀라게하지 않는 것이 좋습니다.
비트 레벨 연산자의 단점.
물어 :
"는 비트 연산자를 사용하지 않은 이유가
&
,|
그리고^
C에서 부울"값 ++에 대한 "는? "
예, 논리 연산자 이며, 높은 수준의 부울 연산자 내장 !
, &&
그리고 ||
, 다음과 같은 장점을 제공합니다 :
보증 인수의 CHAPTER 2 에
bool
에 즉,0
및1
순서 값.최종 결과가 확인되는 즉시 식 평가가 중지되는 평가를 보장 합니다. True , False 및 Indeterminate가
있는 트리 값 논리로 해석 될 수 있습니다 .읽을 수있는 텍스트 등가물
not
,and
및or
, 내가 직접 사용하지 않는 것이 좋습니다.
댓글에 독자 안티몬 노트도 bitlevel 사업자가 다른 토큰을 가지고 즉bitand
,bitor
,xor
와compl
,하지만 내 생각에 이보다 적은 읽을 수and
,or
과not
.
간단히 말해서, 상위 수준 연산자의 단점입니다.
특히 비트 연산자는 0/1 로의 인수 변환이 없기 때문에 예를 들면 1 & 2
→ 0
, 반면 1 && 2
→ true
. 또한 ^
, 비트 배타적 또는이 방식으로 오작동 할 수 있습니다. 부울 값 1과 2는 동일 true
하지만 비트로 패턴되어되어 있습니다.
어떻게 논리를 표현하는 하나 / 또는 C ++에서.
그런 다음 질문에 대한 약간의 배경 지식을 제공하고
"가끔 두 조건 중 정확히 하나가 참 (XOR)이되기를 원하는 상황이 발생하기 때문에 ^ 연산자를 조건식에 넣습니다."
음, 비트 연산자는 논리 연산자 보다 우선 순위 가 높은 . 이것은 특히 다음과 같은 혼합 표현에서
a && b ^ c
예상치 못한 결과를 얻을 수 있습니다 a && (b ^ c)
.
대신 쓰기
(a && b) != c
의미를 더 간결하게 표현합니다.
다중 인수의 경우 / 또는 작업을 수행하는 C ++ 연산자가 없습니다. 당신이 쓰는 예를 들어,보다 a ^ b ^ c
'중 하나라는 표현하지 a
, b
또는 c
사실이다 ". 대신은"홀수의 수를 말한다 a
, b
그리고 c
그들 또는 3의 1이 될 수있는, 참 ... "
일반 중 / 또는 표현하기 위해 a
, b
그리고 c
유형입니다 bool
, 단지 쓰기
(a + b + c) == 1
또는 bool
인수 가 아닌 경우 다음으로 변환하십시오 bool
.
(!!a + !!b + !!c) == 1
&=
부울 결과를 누적하는 데 사용 합니다.
당신은 더 정교하게
"나는 때때로 부울 값을 축적해야하고,
&=
그리고|=?
매우 유용 할 수 있습니다."
글쎄, 이것은 각각 모든 조건이 충족 되는지 또는 어떤 조건이 충족 되는지 확인하는 것과 일치 하며 de Morgan의 법칙 은 하나에서 다른 것으로 이동하는 방법을 알려줍니다. 즉, 그중 하나만 필요합니다. 원칙적 *=
으로 &&=
연산자 로 사용할 수 있습니다 (조지 부울 (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을 사용한 출력 :
진실 그릇된
결과가 다른 이유는 비트 레벨 &=
이 bool
오른쪽 인수 의 변환을 제공하지 않기 때문입니다.
그렇다면이 결과 중 어떤 것을 사용하고 &=
싶습니까?
전자가이면 true
연산자 (예 : 위와 같이) 또는 명명 된 함수를 더 잘 정의하거나 오른쪽 표현식의 명시 적 변환을 사용하거나 전체 업데이트를 작성하십시오.
Patrick의 대답과는 달리 C ++에는 ^^
단락 독점 또는 수행을위한 연산자 가 없습니다 . 잠시 생각해 보면 ^^
연산자를 갖는 것은 어차피 의미가 없을 것입니다. 또는 배타적 또는 결과는 항상 두 피연산자에 따라 달라집니다. 그러나, 비에 대한 패트릭의 경고 bool
비교할 때 "부울"유형은 동일하게 유지 1 & 2
에 1 && 2
. 이에 대한 한 가지 전형적인 예는 Windows GetMessage()
함수로, 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 ++ 컴파일러는 비트 연산의 결과를 bool로 캐스트하려고 할 때 경고합니다. 컴파일러를 행복하게 만들려면 타입 캐스트를 사용해야합니다.
if 표현식에서 비트 연산을 사용하면 컴파일러가 아닌 경우에도 동일한 비판을받을 수 있습니다. 0이 아닌 값은 모두 참으로 간주되므로 "if (7 & 3)"과 같은 것이 참이됩니다. 이 동작은 Perl에서 허용 될 수 있지만 C / C ++는 매우 명시적인 언어입니다. 스팍 눈썹은 실사라고 생각합니다. :) "== 0"또는 "! = 0"을 추가하여 귀하의 목표가 무엇인지 완벽하게 명확히합니다.
그러나 어쨌든 그것은 개인적인 선호처럼 들립니다. Lint 또는 유사한 도구를 통해 코드를 실행하고 그것이 현명하지 못한 전략이라고 생각하는지 확인합니다. 개인적으로는 코딩 실수처럼 읽습니다.
bool에 비트 연산을 사용하면 논리 연산에서 가져온 'cmp'명령으로 인해 프로세서에서 불필요한 분기 예측 논리를 절약 할 수 있습니다.
논리를 비트 연산 (모든 피연산자가 bool 인 경우)으로 대체하면 동일한 결과를 제공하는보다 효율적인 코드가 생성됩니다. 논리 연산을 사용하여 주문할 때 활용할 수있는 모든 단락 이점보다 효율성이 이상적으로 중요합니다.
이것은 프로그래머가 왜 그렇게했는지에 대해 주석을 달아야하지만 코드를 읽을 수 없게 만들 수 있습니다.
참고 URL : https://stackoverflow.com/questions/24542/using-bitwise-operators-for-booleans-in-c
'ProgramingTip' 카테고리의 다른 글
Bash의 텍스트 파일에서 배열 만들기 (0) | 2020.11.08 |
---|---|
콘솔에 인쇄 된 것을 잘리지 마십시오 (RStudio에서). (0) | 2020.11.08 |
Google 크롬 확장 프로그램에서 외부 애플리케이션을 시작 하시겠습니까? (0) | 2020.11.08 |
Golang에서 공유에서 float64로 유형 변환을 사용하여 JSON을 사용하는 방법은 무엇입니까? (0) | 2020.11.07 |
DISTINCT를 사용하여 파티션 함수 COUNT () OVER 가능 (0) | 2020.11.07 |