컴파일러 경고(수준 2) C4146
단항 빼기 연산자가 부호 없는 형식에 적용되었습니다. 결과는 역시 unsigned입니다.
부호 없는 형식은 음수가 아닌 값만 포함할 수 있으므로 부호 없는 형식에 적용할 때는 일반적으로 단항 빼기(부정)가 의미가 없습니다. 피연산자와 결과는 모두 음수가 아닙니다.
설명
음수 정수 리터럴 -
을 표현하면 값 앞의 값이 단항 부정 연산자로 구문 분석됩니다. 컴파일러는 숫자 값을 구문 분석한 후 연산자를 적용합니다. 숫자 값이 부호 없는 정수 형식의 범위에 맞지만 해당 부호 있는 정수 형식이 아닌 경우 컴파일러는 값을 부호 없는 것으로 해석합니다. 부호 없는 값은 단항 부정 연산자에 의해 변경되지 않습니다.
이 경고는 -2147483648 또는 long long
최소 int
값인 -9223372036854775808 표현하려고 할 때 종종 발생합니다. 이러한 값은 각각 -2147483648 또는 -9223372036854775808ll 작성할 수 없습니다. 그 이유는 컴파일러가 식을 두 단계로 처리하기 때문입니다. 먼저 숫자 값을 구문 분석한 다음 부정 연산자를 적용하기 때문입니다. 예를 들어 컴파일러가 -2147483648 구문 분석할 때 다음 단계를 수행합니다.
2147483648 수가 평가됩니다. 2147483647 최대
int
값보다 크지만 여전히 2147483648unsigned int
유형입니다unsigned int
.부호 없는 값에 단항 빼기(unary minus)가 적용되며 부호 없는 결과도 2147483648.
부호 없는 결과 형식으로 인해 예기치 않은 동작이 발생할 수 있습니다. 비교에 결과가 사용되는 경우 다른 피연산 int
자일 때와 같이 부호 없는 비교를 사용할 수 있습니다.
C++ 등가<climits>
를 사용 INT_MIN
하거나 LLONG_MIN
C++에서 <limits.h>
C4146을 방지할 수 있습니다. 이러한 값에는 서명된 형식이 있습니다.
/sdl
(추가 보안 검사 사용) 컴파일러 옵션은 이 경고를 오류로 승격합니다.
예시
다음 샘플에서는 컴파일러에서 경고 C4146을 생성할 때 발생할 수 있는 예기치 않은 동작을 보여 줍니다.
// C4146.cpp
// compile with: /W2
#include <iostream>
void check(int i)
{
if (i > -9223372036854775808ll) // C4146
std::cout << i << " is greater than the most negative long long int.\n";
}
int main()
{
check(-100);
check(1);
}
이 예제에서 컴파일러는 리터럴 ll
에 접미사가 있고 부정 연산자가 적용되더라도 -9223372036854775808ll 부호 없는 것으로 간주합니다. 비교를 <
위해 컴파일러는 자동으로 서명 i
된 수준을 unsigned long long int
승격합니다. 예상되는 두 번째 줄은 1 is greater than the most negative long long int
false이므로 인쇄되지 ((unsigned long long int)1) > 9223372036854775808ull
않습니다.
예제를 수정하려면 -9223372036854775808ll 포함 <climits>
및 변경합니다 LLONG_MIN
.