Union float and int

泪湿孤枕 提交于 2019-12-13 15:36:37

问题


I'm little bit confused. During development of one function that based on predefined parameters, pass to sprintf function exact parameters needed based on their type, I found really strange behaviour ( something like "This is %f %d example", typeFloat, typeInt ).

Please take a look at following stripped working code:

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;
}

My expected output would be for printf( "Number is %d\n", p.paramType == Param::typeInt ? p.i : p.f );

Number is -10

but it actually printed

Number is 0

I have put a breakpoint after initialization of the Param p, and although p.paramType is defined as typeInt, actual output for if was -10.0000. Checking p.f gives some undefined value as expected, and p.i shows -10 also as expected. But p.paramType == Param::typeInt ? p.i : p.f in watch window evaluates to -10.000000.

I added second printf that prints it as float and now the output is

Number is 0
Number is -10.000000

So actually why this happens? Is it possible that this is a bug in Visual Studio (I use VS2012)?

Update:

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

gives correct value of -10.


回答1:


This is because the resulting type of the expression p.paramType == Param::typeInt ? p.i : p.f is always float (only the value is different depending on paramType), but your first format string expects an integer.

The following should work as you expect:

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

The cout version gives you the expected output because the type of the expression being inserted (float) is deduced automatically, and so it formats it as a float. It is essentially the same as your second printf.




回答2:


The problem is twofold. First, it's with printf(). Don't use printf() in C++ code. The reason is related to the second problem. printf() does not have type safety. It does not know what types you gave it.

The second reason is the way types work. Your ternary if statement always returns a float because that's the right-most type. Since an int can be implicitly converted to a float, nothing "bad" happens (unless you're to turn on various "extra" warnings). So p.i gets converted to a float but you're telling printf() to expect an int. Therefore, undefined behavior occurs. Your program doesn't crash but it doesn't give you what you expected.



来源:https://stackoverflow.com/questions/33445690/union-float-and-int

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!