비-유럽 연산자와 부울의 행동
-
18-09-2019 - |
문제
내가 정말로 원하는 것은 || = 운영자입니다.
old_value = old_value || possible_new_value;
old_value ||= possible_new_value;
두 번째 줄은 컴파일러 오류입니다 (C ++에는 || = 연산자가 없습니다).
그래서 내 다른 옵션은 무엇입니까?
old_value += possible_new_value;
old_value |= possible_new_value;
내가 피사체에있는 동안 Bool은 다른 비 불리 사업자와 어떻게 행동합니까?
-
-=
&
&=
...
나는 이것들을 경험적으로 확인할 수 있지만 표준의 말에 가장 관심이 있습니다.
해결책
4.7 (통합 변환)에 따르면 4.6 항에 따르면 "대상 유형이 bool
, 4.12 참조. 소스 유형이있는 경우 bool
, 가치 false
0과 값으로 변환됩니다 true
"4.12에서"산술, 열거, 포인터 또는 멤 bool
. 0 값, 널 포인터 값 또는 널 멤버 포인터 값이 변환됩니다. false
; 다른 값이 변환됩니다 true
."
상황에서 bool
피연산자는 허용되지 않지만 필수 피연산자는 bool
적분 유형으로 변환됩니다. 정수 결과가 a에 저장 될 때 bool
변수는 변환됩니다 bool
.
따라서 + 및 *를 부울 또는 및 및 사용할 수 있으며 사용할 수 있습니다 | 그리고 또한. (bool1 + bool2) & bool3는 산출 할 때 믹싱으로 도망 갈 수 없습니다. false
세 변수가 모두 인 경우 true
. ((1 + 1) & 1은 2 & 1이며, 이는 0 또는 false입니다.)
기억 | 그리고 || 여기에서도 동일하게 작동하지 마십시오. | 양쪽을 평가 한 다음 BitWise 또는를 평가합니다. || 첫 번째 피연산자를 평가하면 False 인 경우에만 두 번째를 평가합니다.
나는 여기서 문체 문제에 대해 논의하지 않을 것이지만, 내가 그런 일을했다면 사람들이 내가하고있는 일과 그 이유를 알도록 댓글을달라고 확신 할 것입니다.
다른 팁
표준은 다음과 같습니다.
4.5-4 "통합 프로모션"
유형 BOOL의 rvalue는 int 유형의 rvalue로 변환 될 수 있으며, 거짓은 0이되고 진실은 하나가됩니다.
5.17-7 "과제 연산자"
E1 OP = E2 형태의 표현의 거동은 E1이 한 번만 평가된다는 점을 제외하고 E1 = E1 OP E2와 동일합니다. in += 및 -=, e1은 산술 유형을 가지거나 CVQUALIFIED 완전히 정의 된 객체 유형에 대한 포인터 여야합니다. 다른 모든 경우에, E1에는 산술 유형이 있어야합니다.
4.12-1 "부울 전환"
산술, 열거, 포인터 또는 멤 0 값, NULL 포인터 값 또는 NULL 멤버 포인터 값은 False로 변환됩니다. 다른 값은 True로 변환됩니다.
그래서 이것은 그것을 의미합니다
b1 += b2
B1과 B2가 부울 인 경우
b1 = b1 + b2
그리고 B1과 B2는 0/1 정수로 홍보 된 다음 0 이외의 다른 것이 사실이라는 규칙에 따라 부울로 다시 변환됩니다.
진실 테이블은입니다
true false true true true false true false
따라서 += 실제로 표준에 따라 || =로 작동합니다. 그러나 이것은 아마도 다른 프로그래머를 혼란스럽게 할 것이므로 여전히 피할 것입니다.
3 원 운영자 만 사용할 수 있습니까?
old_value = !old_value ? possible_new_value : old_value;
사용하지 마십시오 |=
그리고 &=
부울과 함께. 그들은 대부분 일할 수 있지만 여전히 틀립니다. 일반적으로 부울 유형은 영광스러운 int 또는 char입니다. 내가 함께 일한 오래된 코드에서 Bool은 int 또는 char에 대한 typedef'd입니다. 이 경우 비트가 어떻게 든 조작 된 경우 (예 : 1&2
0 (false)). 그리고 나는 확실하지 않지만, Bitwise Operators의 결과는 Bools에게도 INT가 될 것이라고 생각합니다.
if (!old_value)
old_value = possible_new_value;
이것은 원래 조건과 직접적으로 동일합니다. 항상 할당되지 않기 때문에 더 간단한 코드를 생성 할 수 있습니다. old_value
- 그러나 나는 큰 프로그램에서 성능 차이가 쉽게 측정 할 수있을 것으로 기대하지 않을 것입니다.
한 가지 차이점은 다음과 같은 논리 연산자입니다 ||
평가 순서를 보장하고 비트 와이즈 및 산술 연산자가없는 곳에서 단락을 제공합니다.
컴파일러는 부울을 숫자 값 (0, 1)으로 변환하여 연산자를 적용하고 뒤로 변환하여 비-로그 연산자를 처리 할 것이라고 생각합니다. 이러한 변환은 표준에 의해 엄격하게 정의됩니다.
산술, 열거, 포인터 또는 멤 0 값, NULL 포인터 값 또는 NULL 멤버 포인터 값은 False로 변환됩니다. 다른 값은 True로 변환됩니다.
끔찍한 매크로 해커 :
#define UPDATE(x) x = x
UPDATE(old_value) || possible_new_value;
그러나 나는 이것을 전혀 추천하지 않습니다. 이와 같은 매크로는 몇 가지 이유로 매우 나쁜 생각입니다.
보다 제정신 기능이지만 단락없이 :
bool set_or(bool &old, bool value) {
return (old = old || value);
}
...
bool v = false;
set_or(v, true);
표준은 진실과 거짓을 명시 적으로 1과 0으로 정의한다고 생각하므로 비트 연산자를 안전하게 사용할 수 있습니다. bool
가치. 다른 맥락에서 암시 적으로 부울로 취급 될 수있는 다른 유형은 이것을 안정적으로 작동하도록 명시 적으로 변환되어야합니다.
Microsoft의 컴파일러가 INT 결과를 BOOL로 다시 변환하는 데 위험이 있다고 생각하기 때문에 Microsoft의 컴파일러 가이 작업을 수행 할 때마다 추악한 경고를 생성하는 것을 보았습니다.