联合浮点数和整数
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(只有 value 因 paramType
而异),但您的第一个格式字符串需要一个整数。
以下应该会如您所愿:
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
。因此,会发生未定义的行为。您的程序不会 崩溃 但它不会给您预期的结果。
我有点困惑。在开发一个基于预定义参数的函数时,根据类型向 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(只有 value 因 paramType
而异),但您的第一个格式字符串需要一个整数。
以下应该会如您所愿:
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
。因此,会发生未定义的行为。您的程序不会 崩溃 但它不会给您预期的结果。