Searching for explicit conversion of a pointer to a 32-bit type

19.10.2010 Andrey Karpov

In Visual Studio C++ compiler, there is the warning C4311 ('variable' : pointer truncation from 'type' to 'type') intended to detect errors of casting a pointer to 32-bit data types. This warning corresponds to warning #810 in Intel C++. This is an example of the defect they diagnose:

void *ptr = x;
int y = (int)ptr;

In Win64, the pointer's size is 64-bit while the int type's size is still 32 bits. Explicit type conversion truncates the pointer's value, which will cause an error in case the pointer refers to an object situated outside the first 4 low-order Gbytes (0x00000000FFFFFFFF).

What is bad about such errors is that they occur irregularly. But you can easily find them reviewing all the compiler's warnings with number C4311. However, there is a subtle unpleasant trouble about using this very diagnosis.

If you simply create a 64-bit project in Visual Studio 2008/2010 and write the above mentioned code, you will not get the C4311 warning. Let's find out why.

In Visual Studio 2003/2005, there is the /Wp64 switch intended for detecting some problems the programmer will encounter when building his code in the 64-bit version. Warning C4311 is among these warnings. If you create a project in Visual Studio 2005, the warning will be generated even in the 32-bit configuration for the line "int y = (int)ptr;":

warning C4311: 'type cast' : 
pointer truncation from 'void *' to 'int'.

The /Wp64 switch was meant to at least somehow prepare applications for the 64-bit platform without creating the 64-bit configuration. However, the time of "getting ready" has passed. Starting with Visual Studio 2005, the environment provides a 64-bit compiler. If you want to support both Win32 and Win64 platforms, you must have two configurations of your project. It is unreasonable to use the /Wp64 switch in x64 configuration, so it was declared deprecated in Visual Studio 2008/2010.

Everything would be all right, but it seems to me that Visual Studio developers made a logical mistake. If you create a new project in Visual Studio 2008/2010 or convert an old project into a new one, the /Wp64 switch will be disabled. It is ok. Even if you define /Wp64 deliberately in the project's "Additional Options", you will get this message:

Command line warning D9035: 
option 'Wp64' has been deprecated and will be removed in a future release.

What is humorous about this situation is that warnings C4311, C4312 and C4313 are still related to the /Wp64 switch for some reason. If the switch is absent, these warnings are absent as well, although they have Danger Level 1.

These warnings will come back if you enable /Wp64 and get warnings D9035 about an obsolete option. Another way is to enable /Wall. The messages you need will be generated, but this way, as you may see, is only for the brave ones. Using #pragma warning in stdafx.h seems to be the most reasonable way.

Now let's speak about Intel C++. When I started studying this issue, I was expecting that its behavior concerning /Wp64 was similar to that of Visual C++. But I found out that it went its own way. It detected the conversion error of the "int y = (int)ptr;" kind even without the /Wp64 switch by generating warning #810. But warning #967 (equivalent to C4312) demanded /Wp64. It turns out that the Intel C++ compiler also has a set of warnings related to /Wp64 but the set itself is different. Since it is a historically established situation that there is no documentation on exotic specifics of Intel C++, I failed to find out what particular thing enables /Wp64.

After this flow of thoughts and words, the readers may ask:

What is the problem after all? Tell me again in short, please.

Here is the answer. If you have a project for Visual Studio 2008/2010 and create the 64-bit configuration, you will fail to see warnings for trivial errors like these:

void *ptr = x;
int y = (int)ptr; // C4311

int i = x;
return (void*)i; // C4312

int * pI = 0;
printf("%d", pI); // C4313

and perhaps for some others too. If you build the same project with Intel C++, you will fail to get another set of errors.

To get all those good warnings, you must enable them yourself! It is not hard to do if you know about it. As for me, I have not known about it, although I am involved in the sphere of 64-bit software development.

I want to point it out that conquering these warnings does not necessarily mean making a 64-bit program correct. It only means that you have fixed the most obvious defects - so to say, "who doesn't hide, I will find". But to find "those who hide" in large projects, you should use specialized tools (Viva64).

Of course, I was not the first who noticed this defect concerning 64-bit warnings. A comment on this topic was posted right recently here. Note that the criticism is very fresh.

Summing it all, I may say that people are only beginning to get interested in creating Win64 applications. I wrote this phrase a year ago and now repeat it again. It is very strange. I do not believe that one can develop good applications without studying places where a pointer is crammed into the int type. Absence of mass discussions of such issues on the Internet embarrasses me very much. I do not understand how the world is arranged.