Our website uses cookies to enhance your browsing experience.
Accept
to the top
close form

Fill out the form in 2 simple steps below:

Your contact information:

Step 1
Congratulations! This is your promo code!

Desired license type:

Step 2
Team license
Enterprise license
** By clicking this button you agree to our Privacy Policy statement
close form
Request our prices
New License
License Renewal
--Select currency--
USD
EUR
* By clicking this button you agree to our Privacy Policy statement

close form
Free PVS‑Studio license for Microsoft MVP specialists
* By clicking this button you agree to our Privacy Policy statement

close form
To get the licence for your open-source project, please fill out this form
* By clicking this button you agree to our Privacy Policy statement

close form
I am interested to try it on the platforms:
* By clicking this button you agree to our Privacy Policy statement

close form
check circle
Message submitted.

Your message has been sent. We will email you at


If you do not see the email in your inbox, please check if it is filtered to one of the following folders:

  • Promotion
  • Updates
  • Spam

Webinar: C++ semantics - 06.11

>
>
>
V1112. Comparing expressions with diffe…
menu mobile close menu
Analyzer diagnostics
General Analysis (C++)
General Analysis (C#)
General Analysis (Java)
Micro-Optimizations (C++)
Diagnosis of 64-bit errors (Viva64, C++)
Customer specific requests (C++)
MISRA errors
AUTOSAR errors
OWASP errors (C#)
Problems related to code analyzer
Additional information
toggle menu Contents

V1112. Comparing expressions with different signedness can lead to unexpected results.

Aug 02 2024

The analyzer has detected a suspicious comparison where expression types have the same ranks but different signs. So, the type ranks are smaller than the 'int' rank. Since such expressions are implicitly converted to the 'int' or 'unsigned int' type, the comparison may lead to unexpected results.

Consider the synthetic example:

bool foo(char lhs, unsigned char rhs)
{
  return lhs == rhs; // <=
}

The example contains the variable comparison with types of different signedness: 'lhs' of the 'char' type and 'rhs' of the 'unsigned char' type. Let's consider that the following 'char' type is the 'signed char' (for example, on the x86_64 architecture). The 'unsigned char' type can cover a range of [0 .. 255], while the 'char' type covers [-128 .. 127]. According to C and C++ standards, an implicit type conversion (integral promotion) occurs before variable values are compared, which may cause the issue.

The compiler transforms the code with the comparison into the following code:

return (int) lhs == (int) rhs;

The compiler converts it in such a way if the 'int' type can cover the 'char' and 'unsigned char' range. Otherwise, the compiler selects 'unsigned int' instead of 'int'. On most modern platforms, the 'int' type has a size of 4 bytes and can easily cover these ranges.

If 'lhs' had a negative value, the same value is saved in the left operand as a conversion result. The value of the right operand after the 'rhs' conversion is always non-negative, because the original type was unsigned. So, the comparison result is 'false'. A user can have the opposite case. If the 'rhs' variable contains a value in the range of [128 .. 255], then the comparison result is also 'false'.

If the user changes the compiler or configuration, this error may occur. It can happen when the 'char' type was unsigned before and became signed, and vice versa. For example, when the user calls the 'foo' function with the '\xEE' and '\xEE' arguments, unequal values are passed. According to the standard, this behavior is logical, but it may also be unexpected by the developer.

The user can avoid this in two approaches:

Approach N1. Convert expressions to a common type by sign:

if ((unsigned char) lhs == rhs)

Approach N2. Use the 'std::cmp_*' functions (C++20) or their analogs to compare expressions which types have different signedness:

if (std::cmp_equal(lhs, rhs))

Note: the diagnostic rule implements several exceptions that are added to reduce the number of false positives. The analyzer issues a warning only if it has been able to prove that the value range of one operand cannot be represented by the type of the other operand. If you need to detect all the fragments in the code where such an operand comparison of different signedness occurs, you may use the following comment:

//+V1112, ENABLE_ON_UNKNOWN_VALUES

For this reason, the analyzer does not issue a warning for the synthetic example given earlier without this setting.

This diagnostic is classified as: