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

>
>
>
Warning C4267 in the expression unsigne…

Warning C4267 in the expression unsigned n = str.find(substr)

Jan 23 2012
Author:

When porting 32-bit code on a 64-bit system, Visual C++ compiler may generate a lot of warnings C4267 for the code where the result of the function std::string::find() is saved into a variable of the unsigned type.

Here is such an example:

using namespace std;
string s("123456789");
unsigned n = s.find("a");
if (n == string::npos)
  cout << "OK" << endl;
else
  cout << "64-bit error" << endl;

The function find() returns the value of the type string::size_type that in practice is analogous to the type size_t. In a 32-bit program the types string::size_type and unsigned coincide and have the size 32 bits.

When compiling the code example given above in the 64-bit mode, the compiler generates the following warning:

warning C4267: 'initializing' : 
conversion from 'size_t' to 'unsigned int', possible loss of data

The reason for that is that the size of the type string::size_type extends to 64 bits in a 64-bit program. Accordingly, the compiler warns you about a loss of significant bits when the 64-bit type is implicitly converted to the 32-bit type.

When studying this case, programmers often make this logical mistake:

My program never has and will never have strings longer than some Kbytes and Gbytes all the more. So, the unsigned type is quite enough to keep the position of the substring found.

The result of such a supposition is that programmers suppress the compiler warning with an explicit type conversion. It allows them to correct only one fragment of the code without involving the following ones. Below is the code "corrected" in this way:

using namespace std;
string s("123456789");
unsigned n = (unsigned)s.find("a");
if (n == string::npos)
  cout << "OK" << endl;
else
  cout << "64-bit error" << endl;

This way of correction is bad. The code contains an error and the warning that could help detect it is now suppressed with the explicit type conversion. If you launch this code in the 64-bit mode, it will print the message "64-bit error" instead of "OK".

The error occurs because the function find() returns the value string::npos that equals 0xFFFFFFFFFFFFFFFFui64. This value is cut to the size 0xFFFFFFFFu and saved into a 32-bit variable. As a result, the condition 0xFFFFFFFFu == 0xFFFFFFFFFFFFFFFFui64 is always false.

To correctly fix such warnings you should use correct types instead of suppressing them with explicit type conversions. In our case we should use a variable of the type string::size_type to store the result. Here is an example of a proper correction of the code:

using namespace std;
string s("123456789");
string::size_type n = s.find("a");
if (n == string::npos)
  cout << "OK" << endl;
else
  cout << "64-bit error" << endl;

Of course, string::size_type makes the code a bit complicated and less readable, so you can compromise between full accuracy and simplicity of the code using the type size_t. But this is up to you what to choose.

The compiler warning C4267 is useful because it allows you to detect various 64-bit errors. Unfortunately, sometimes this warning may be suppressed by an explicit type conversion that was written when developing the 32-bit code. In this case you may use the static analyzer Viva64 included into PVS-Studio to diagnose the related issues. The analyzer generates the diagnostic warnings V201 and V202 that allow you to detect unsafe explicit type conversions when developing 64-bit applications.

Popular related articles


Comments (0)

Next comments next comments
close comment form