Click here to Skip to main content
Click here to Skip to main content

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

, 25 Mar 2012 CPOL
Rate this:
Please Sign up or sign in to vote.
When porting 32-bit code on a 64-bit system, Visual C++ compiler may generate a lot of warnings

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Karpov Andrey
Architect Program Verification Systems, Co Ltd
Russian Federation Russian Federation

Andrey Karpov is technical manager of the OOO "Program Verification Systems" (Co Ltd) company developing the PVS-Studio tool which is a package of static code analyzers integrating into the Visual Studio development environment.

PVS-Studio is a static analyzer that detects errors in source code of C/C++ applications. There are 3 sets of rules included into PVS-Studio:

  1. Diagnosis of 64-bit errors (Viva64)
  2. Diagnosis of parallel errors (VivaMP)
  3. General-purpose diagnosis

Awards: MVP, Intel Black Belt

Andrey Karpov is also the author of many articles on the topic of 64-bit and parallel software development. To learn more about the PVS-Studio tool and sources concerning 64-bit and parallel software development, please visit the www.viva64.com site.

Best Articles:

My page on LinkedIn site: http://www.linkedin.com/pub/4/585/6a3

E-mail: karpov@viva64(dot)com

Follow on   Twitter

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web02 | 2.8.141015.1 | Last Updated 26 Mar 2012
Article Copyright 2012 by Karpov Andrey
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid