联合浮点数和整数

Union float and int

我有点困惑。在开发一个基于预定义参数的函数时,根据类型向 sprintf 函数传递所需的确切参数,我发现了非常奇怪的行为(类似于 "This is %f %d example"、typeFloat、typeInt)。

请查看以下剥离的工作代码:

struct Param {
 enum { typeInt,    typeFloat   } paramType;
 union {
    float f;
    int i;
 };
};

int _tmain(int argc, _TCHAR* argv[])
{
 Param p;
 p.paramType = Param::typeInt;
 p.i = -10;

 char chOut[256];
 printf( "Number is %d\n", p.paramType == Param::typeInt ? p.i : p.f );
 printf( "Number is %f\n", p.paramType == Param::typeInt ? p.i : p.f );
 return 0;
}

我的预期输出是 printf( "Number is %d\n", p.paramType == Param::typeInt ? p.i : p.f );

Number is -10

但它实际上打印了

Number is 0

我在 Param p 初始化后设置了一个断点,虽然 p.paramType 定义为 typeInt,但 if 的实际输出是 -10.0000。检查 p.f 会按预期给出一些未定义的值,并且 p.i 也会按预期显示 -10。 但是 p.paramType == Param::typeInt ? p.i : p.f 在 watch window 中的计算结果为 -10.000000.

我添加了第二个 printf,将其打印为浮点数,现在输出为

Number is 0
Number is -10.000000

那么实际上为什么会发生这种情况?这可能是 Visual Studio(我使用 VS2012)中的错误吗?

更新:

std::cout<< (p.paramType == Param::typeInt ? p.i : p.f);

给出正确的值 -10。

这是因为表达式 p.paramType == Param::typeInt ? p.i : p.f 的结果类型始终是 float(只有 valueparamType 而异),但您的第一个格式字符串需要一个整数。

以下应该会如您所愿:

printf("Number is %d\n", (int)(p.paramType == Param::typeInt ? p.i : p.f));

cout 版本为您提供了预期的输出,因为插入的表达式 (float) 的类型是自动推断的,因此它将其格式化为浮点数。它与您的第二个 printf.

基本相同

问题是双重的。首先,它是 printf()。不要在 C++ 代码中使用 printf()。原因与第二个问题有关。 printf() 没有类型安全。它不知道你给它什么类型。

第二个原因是类型的工作方式。你的三元 if 语句总是 returns a float 因为那是最右边的类型。由于 int 可以隐式转换为 float,因此 "bad" 不会发生(除非您要打开各种 "extra" 警告)。所以 p.i 被转换为 float 但你告诉 printf() 期待 int。因此,会发生未定义的行为。您的程序不会 崩溃 但它不会给您预期的结果。