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

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:

```cpp
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](https://pvs-studio.com/en/blog/terms/0044/)\. 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:

```cpp
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:

```cpp
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:

```cpp
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](https://pvs-studio.com/en/blog/terms/0002/)\. 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](https://pvs-studio.com/en/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\.