【发布时间】:2021-10-20 05:35:08
【问题描述】:
示例代码(t0.c):
#include <stdio.h>
#include <limits.h>
#define F 2147483600.0f
int main(void)
{
printf("F %f\n", F);
printf("INT_MAX %d\n", INT_MAX);
printf("F <= INT_MAX %d\n", F <= INT_MAX);
if ( F <= INT_MAX )
{
printf("(int)F %d\n", (int)F);
}
return 0;
}
调用:
$ gcc t0.c && ./a.exe
F 2147483648.000000
INT_MAX 2147483647
F <= INT_MAX 1
(int)F 2147483647
$ clang t0.c && ./a.exe
F 2147483648.000000
INT_MAX 2147483647
F <= INT_MAX 1
(int)F 0
问题:
- 如果
F打印为2147483648.000000,那么为什么F <= INT_MAX为真? - 在这里避免 UB 的正确方法是什么?
UPD。解决方案:
if ( lrintf(F) <= INT_MAX )
{
printf("(int)F %d\n", (int)F);
}
UPD2。更好的解决方案:
if ( F <= nextafter(((float)INT_MAX) + 1.0f, -INFINITY) )
{
printf("(int)F %d\n", (int)F);
}
【问题讨论】:
-
float意义不够。 -
可以加
printf("INT_MAX as float %f\n", (float)INT_MAX);吗?如果它打印出2147483648,那么您就知道为什么if为真。 -
请记住,
float类型(或任何非无限浮点类型)的有限精度可以应用于小数点的左侧和右侧。没有像 2147483600 这样的float数字。最接近的可表示float值是 2147483648。 -
使用
if ( F <= nextafter(((float)INT_MAX) + 1.0f, -INFINITY) ),是nextafterf()的意图,还是您建议使用double函数? IAC,您的解决方案不属于问题,而是作为您自己的答案的帖子,可以对其进行正确评级。 -
if ( lrintf(F) <= INT_MAX )是错误的,而(float) INT_MAX是准确的。例如16 位int、64 位float。
标签: c type-conversion undefined-behavior c11 c17