C++20을 사용해 봅시다 | std::cmp_* 함수

오늘 저는 C++20: the std::cmp_* functions 에서 매우 간단하지만 매우 효율적이고 유용한 기능을 발견했습니다. 암시적 변환에 영향을 받지 않고 부호가 다를 수 있는 2개의 정수를 비교할 수 있습니다.

이 코드를 살펴보겠습니다.

#include <iostream>

int main()
{
    int a = -6;
    unsigned int b = 3;

    if (a < b) {
        std::cout << "OK: a is lower than b\n";
    } else {
        std::cout << "Oopsi!\n";
    }
}


네, 맞습니다. "Oopsi!"가 인쇄됩니다.

왜요?

Rule RSPEC-6214 from Sonar은 이 문제를 다음과 같이 잘 설명합니다.

Comparison between signed and unsigned integers is dangerous because it produces counterintuitive results outside of their common range of values.

When a signed integer is compared to an unsigned one, the former might be converted to unsigned. The conversion preserves the two’s-complement bit pattern of the signed value that often corresponds to a large unsigned result. For example, 2U < -1 is true.

C++20 introduced remedy to this common pitfall: a family of std::cmp_* functions defined in the header. These functions correctly handle negative numbers and lossy integer conversion. For example, std::cmp_less(2U, -1) is false.

This rule reports comparisons between signed and unsigned integers that involve negative numbers.



해보자:

#include <iostream>
#include <utility>

int main()
{
    int a = -6;
    unsigned int b = 3;

    if (std::cmp_less(a, b)) {
        std::cout << "OK: a is lower than b\n";
    } else {
        std::cout << "Oopsi!\n";
    }
}


이제 코드는 "OK: is lower than b"를 출력합니다 😁

컴파일러는 이와 같은 변환에 대한 경고를 표시할 수 있습니다. GCC를 사용하면 옵션-Wall으로 충분합니다.

<source>: In function 'int main()':
<source>:10:11: warning: comparison of integer expressions of different signedness: 'int' and 'unsigned int' [-Wsign-compare]
   10 |     if (a == b) {
      |         ~~^~~~


문제는 C에서 동일하지만 -Wall는 C에 대해 -Wsign-compare를 추가하지 않고 C+에서만 추가합니다.

추신: dev.to에서는 재미있는 정수 변환에 관한 것이었습니다(그러나 읽으려면 프랑스어를 말해야 합니다 😅)

좋은 웹페이지 즐겨찾기