부울 연산자 ++ 및-


104

오늘 Visual C ++ 코드를 작성하는 동안 저를 놀라게 한 무언가를 발견했습니다. C ++는 bool에 대해 ++ (증가)를 지원하지만-(감소)는 지원하지 않는 것 같습니다. 이것은 단지 임의의 결정일 뿐입니 까, 아니면 그 뒤에 어떤 이유가 있습니까?

이것은 다음을 컴파일합니다.

static HMODULE hMod = NULL;
static bool once = false;
if (!once++)
    hMod = LoadLibrary("xxx");

이것은하지 않습니다 :

static HMODULE hMod = NULL;
static bool once = true;
if (once--)
    hMod = LoadLibrary("xxx");

2
hm, xcode 및 gcc 컴파일러의 경우 동일
Vladimir

네, ++onceonce++GCC와 업무가 아니라 감소합니다.
Justin Ardini 2010 년

아마도 "연산자 키워드"대신 "역사"태그를 다시 지정할 수 있습니다. 그러면 역사를 고려하면 왜 다양한 미친 것들이 합리적인지에 대한 다른 모든 재미있는 설명과 함께 그룹화됩니다. :)
Jon Hanna

C ++ 17부터 for pre-increment 연산자 bool는 더 이상 사용되지 않습니다. souce .
cogle

이것은 교체 할 수 있습니다 std::exchange(once,false): (주 하지 당신이 뭔가 비 사용되지 원하는 경우, 원자).
golvok

답변:


90

정수 값을 부울로 사용한 역사에서 비롯됩니다.

경우 x입니다 int,하지만 난에 따라 부울로 사용하고 if(x)...다음 작업을하기 전에 그 무엇이든 그것의 진리 값을 의미합니다 증가, 그것의 진리 값 것이다 true뒤에 (오버 플로우를 금지 참조).

그러나 (적분 값이 1 인 경우) 또는 (적분 값이 다른 경우-특히 여기에는 0 [ ] 및 2가 포함됨 ) 결과가 발생할 수 있으므로 --의 진리 값에 대해서만 주어진 지식 의 결과를 예측하는 것은 불가능합니다. 더 [xfalsetruefalsetrue ]).

그래서 짧은 손으로 ++일했으며,-- 가 있었지만 그렇지 않았습니다.

++ 이것과의 호환성을 위해 bools에서 허용되지만 표준에서는 더 이상 사용되지 않습니다.


이것은 내가 부울 로만 사용 한다고 가정합니다. 즉 x, ++자체적으로 오버플로를 일으킬만큼 자주 수행 할 때까지 오버플로가 발생할 수 없습니다 . char을 사용하는 유형으로 CHAR_BITS5와 같이 낮은 값을 사용하더라도 더 이상 작동하지 않는 32 배입니다 (아직도 나쁜 습관 이기에 충분한 논쟁입니다. 나는 연습을 방어하는 것이 아니라 작동하는 이유 만 설명합니다) 32 비트 int의 경우 당연히 ++이것이 문제가되기 전에 2 ^ 32 번 사용해야 합니다. 에 대해 1의 값으로 시작하거나 0으로 시작하여 정확히 한 번 사용 --false경우 에만 결과가 나타 납니다 .true++

0보다 약간 낮은 값으로 시작하는 경우에는 다릅니다. 실제로 이러한 경우 다음 과 같은 값을 최종적 ++으로 얻을 수 있습니다 false.

int x = -5;
while(++x)
  doSomething(x);

그러나,이 예를 취급 x하여 AS int조건을 제외한 모든 곳은, 그래서 동등입니다 :

int x = -5;
while(++x != 0)
  doSomething(x);

x부울 로만 사용하는 것과 다릅니다 .


1
감사합니다. 내가 실제로 C ++ 한 줄을 작성한 이후로 얼마나 오래 되었는가를 감안할 때, 이런 질문에 대해 사람들에게 여전히 답을 줄 수 있다는 사실을 알게되어
기쁩니다.

8
그러나 x가 -1 (VB와 같은 일부 플랫폼에서는 TRUE)이면 ++ x는 FALSE입니다.
제임스 커런

4
@James, C 및 C ++에서 내가 말했을 때 생각했던 경우입니다 ( "오버플로 금지"). 실제로 VB에서 0이 아닌 모든 값은 TRUE (C에서와 같이) 값이 TRUE이지만 NOT (TRUE)이 FALSE이고 NOT (FALSE)가 TRUE, x OR이므로 참 부울 연산의 결과로 1이 아닌 -1이 있습니다. TRUE는 TRUE, x OR FALSE는 x, x AND FALSE는 FALSE, x AND TRUE는 x 등 부울 및 비트 연산에 대해 동일한 연산자를 사용합니다 (VB는 2의 보수를 가정하므로 -1은 모두 1 비트입니다). 그러나 코더가 2 (true)와 4 (true) 결과가 0 (false)임을 파악하지 못하면 VB에서 이상한 버그가 발생할 수 있습니다.
Jon Hanna

2
@JonHanna : ANSI C89는 최초의 C 표준이었습니다. ANSI C위원회는 <limits.h>헤더와 CHAR_BIT매크로를 발명했습니다 . 그 전에는 이론적으로 char8 비트보다 좁은 구현이있을 수 있다고 생각 하지만 내가 아는 한 아무것도 없었습니다. 특히 K & R1 (1978 년 발행)에는 4 개의 샘플 구현이 나열되어 있으며, 모두 8 비트 또는 9 비트 char.
Keith Thompson

1
@JonHanna : 한 준수 C 구현 해야한다 있습니다 CHAR_BIT >= 8. 표준은 그것이 어려운 대상을 허용하지 않습니다. (당신은 물론 부적합 구현을 가질 수 있습니다.)
키이스 톰슨

29

ANSI ISO IEC 14882 2003 (c ++ 03) :

5.2.6-2

postfix의 피연산자-피연산자가 bool 유형이 아니라는 점을 제외하면 postfix ++ 연산자와 유사하게 감소합니다. [참고 : 접두사 증가 및 감소에 대해서는 5.3.2를 참조하십시오. ]

그리고 당연히 ...

5.3.2-2

접두사의 피연산자-1을 빼서 수정합니다. 피연산자는 bool 유형이 아니어야합니다. 접두사의 피연산자에 대한 요구 사항과 그 결과의 속성은 그렇지 않으면 접두사 ++의 요구 사항과 동일합니다. [참고 : 후위 증가 및 감소에 대해서는 5.2.6을 참조하십시오. ]

또한 5.6.2-1 및 5.3.2-1에서는 ++ for bool이 참이어야한다고 언급하고 Annex D-1에서는 ++ on bool이 더 이상 사용되지 않는다고 말합니다.


3
@BlueRaja : Jon Hanna의 답변을 참조하십시오.
Justin Ardini 2010 년

9

역사적 이유 때문에 이것이 지원되었습니다. 그러나 ++ 연산자와 함께 bool 유형의 피연산자를 사용하는 것은 더 이상 사용되지 않습니다. C ++ 표준 (n3092)의 섹션 5.3.2를 참조하십시오.

5.3.2 증가 및 감소 [expr.pre.incr]

  • 접두사 ++의 피연산자는 1을 추가하여 수정하거나 bool이면 true로 설정합니다 (이 사용은 더 이상 사용되지 않음). 피연산자는 수정 가능한 lvalue 여야합니다. 피연산자의 유형은 산술 유형이거나 완전히 정의 된 객체 유형에 대한 포인터 여야합니다. 결과는 업데이트 된 피연산자입니다. lvalue이고 피연산자가 비트 필드 인 경우 비트 필드입니다. x가 bool 유형이 아닌 경우 표현식 ++ x는 x + = 1과 같습니다 [참고 : 변환에 대한 정보는 더하기 (5.7) 및 할당 연산자 (5.17)에 대한 설명을 참조하십시오. —end note]
  • 접두사의 피연산자-1을 빼서 수정합니다. 피연산자는 bool 유형이 아니어야합니다. 접두사의 피연산자에 대한 요구 사항과 그 결과의 속성은 그렇지 않으면 접두사 ++의 요구 사항과 동일합니다.

3
  • 이전 표준 (C ++ 98)에서는 오류가 아닙니다.
  • 새로운 표준이 증가함에 따라 부울은 더 이상 사용되지 않습니다. (C ++ 11)
  • C ++ 17까지 부울에 증분을 사용할 수 있습니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.