前几天我将我的 Windows 构建环境从 MSVC2013 升级到 MSVC2017,你瞧,我的程序中一个多年来一直运行良好的函数(在 g++/clang 下仍然运行良好)在使用 MSVC2017 编译时突然开始给出不正确的结果.
我能够重新编写函数以再次给出正确的结果,但这种体验让我感到好奇——我的函数是否调用了未定义的行为(直到现在才恰好给出正确的结果),或者代码是否定义明确并且 MSVC2017 正在越野车?
下面是一个简单的程序,显示了我重写之前和之后的玩具版本。特别是,当使用值为 -32762 的参数调用时,如下所示的函数 maybe_invokes_undefined_behavior() 是否会调用未定义的行为?
#include <stdio.h>
enum {ciFirstToken = -32768};
// This function sometimes gives unexpected results under MSVC2017
void maybe_invokes_undefined_behavior(short token)
{
if (token >= 0) return;
token -= ciFirstToken; // does this invoke undefined behavior if (token==-32762) and (ciFirstToken==-32768)?
if (token == 6)
{
printf("Token is 6, as expected (unexpected behavior not reproduced)\n");
}
else
{
printf("Token should now be 6, but it's actually %i\n", (int) token); // under MSVC2017 this prints -65530 !?
}
}
// This function is rewritten to use int-math instead of short-math and always gives the expected result
void allgood(short token16)
{
if (token16 >= 0) return;
int token = token16;
token -= ciFirstToken;
if (token == 6)
{
printf("Token is 6, as expected (odd behavior not reproduced)\n");
}
else
{
printf("Token should now be 6, but it's actually %i\n", (int) token);
}
}
int main(int, char **)
{
maybe_invokes_undefined_behavior(-32762);
allgood(-32762);
return 0;
}