기타 Hacker News · 4시간 전

C++에서는 참(true)을 뒤집어도 참(true)이 나오는 기묘한 이유

핵심 요약
  • C++에서 bool 값에 비트 부정 연산자(~)를 적용한 뒤 다시 bool로 캐스팅하면 놀랍게도 true가 그대로 나옵니다.
  • 이는 int보다 작은 정수형이 비트 연산 시 int로 강제 승격된 뒤, 0이 아닌 값(-2)이 다시 bool로 변환되면서 1(true)로 처리되기 때문입니다.
  • 심지어 컴파일러에 따라 어셈블리 변환 방식 차이로 인해 결과가 false로 달라지는 등 난해한 엣지 케이스를 보여줍니다.
요약 C++ 언어에서 비트 부정(보수) 연산자를 참(true) 값에 적용했을 때 발생하는 기묘한 현상이 개발자 커뮤니티에서 화제가 되었습니다. 글쓴이는 C++26 표준 제안서인 P4313R1(열거형을 위한 비트마스크 연산 지원 제안)을 살펴보던 중, C++의 정수 승격(integral promotion)과 불리언 변환 규칙이 맞물려 일어나는 예상 밖의 동작을 짚어냈습니다. C++ 컴파일러는 `int`보다 크기가 작은 정수형(예: short, char, bool 등)에 비트 연산을 수행할 때, 이들을 직접 계산하지 않고 중간 단계에서 먼저 `int` 타입으로 정수 승격을 거치게 합니다. 승격 자체는 강제적인 규칙이며 개발자가 건너뛸 수 없습니다. 여기에 불리언 변환의 특수성이 더해지는데, 0이 아닌 모든 값은 1(true)로 치환되는 규칙이 적용됩니다. 이 두 가지 원리가 합쳐지면 독특한 결과가 나옵니다. `~true`를 계산한 뒤 이를 다시 `bool` 타입으로 캐스팅(`static_cast<bool>(~true)`)하면, 먼저 `true`가 1로 승격되고 1의 보수 연산 결과 -2가 됩니다. 이후 다시 `bool`로 변환되는 과정에서 -2는 0이 아니기 때문에 최종적으로 `true`가 반환되어, 결국 'true의 보수는 true'라는 역설적인 결과가 성립합니다. 심지어 기반 타입이 `bool`인 열거형(enum class)에 대해서는 GCC 컴파일러가 어셈블리 생성 시 단순 하위 비트 AND 마스킹을 수행해 `false`를 내놓는 등 컴파일러별 불일치까지 발견되어 프로그래밍 언어 사양의 흥미로운 구석을 보여줍니다.
Sponsored · 광고