为什么GCC会对这种隐式转换发出警告?

为什么GCC会对这种隐式转换发出警告?,c,gcc,type-conversion,compiler-warnings,C,Gcc,Type Conversion,Compiler Warnings,GCC警告我,以下代码段包含可能更改值的隐式转换: #include <stdlib.h> float square = rand(); GCC发出的警告如下: tests/ChemTests.cpp:17:23: error: conversion to ‘float’ from ‘int’ may alter its value 我不明白为什么前者会给出警告,因为rand()正确声明并返回int,就像100整数文本一样 为什么第一行给出编译器警告而第二行没有,即使两者都有从i

GCC警告我,以下代码段包含可能更改值的隐式转换:

#include <stdlib.h>
float square = rand();
GCC发出的警告如下:

tests/ChemTests.cpp:17:23: error: conversion to ‘float’ from ‘int’ may alter its value
我不明白为什么前者会给出警告,因为
rand()
正确声明并返回
int
,就像
100
整数文本一样


为什么第一行给出编译器警告而第二行没有,即使两者都有从
int
float
的隐式转换?

当强制转换可能导致精度损失时,GCC会发出此警告。(换言之,价值可能会被“更改”)

在第一种情况下,
rand()
返回一个
int
。由于并非所有可存储在
int
中的值都可表示为
浮点值,因此它将发出此警告


在第二种情况下,100可以安全地强制转换成一个
浮点数
,而不会有任何精度损失。

为了增加神秘主义所写的内容(这是正确的):您的C实现使用的
浮点数和
int
是32位。在“your”
int
中,可以有31位数字和1位符号。在“您的”浮点中,
尾数是24位,有1位符号。显然,需要超过24位加号来表示的
int
s不能准确地转换为“your”
float
。(我用“your”来表示“your”编译器,即您正在使用的编译器。C标准没有告诉
float
int
的确切长度)

现在,
rand()
可以生成任何
int
数字,因此编译器必须向您发出警告。
100
是编译时已知的数字文本,因此编译器可以静态检查该数字是否可转换

(即使没有解释浮点的具体工作原理,你的
int
还是32位,只“支持”整数。你的
float
是32位,并且“支持”浮点数。显然,浮点数更难表示(你必须将小数点保存在某个地方),因此必须有一个“价格”如果
int
float
长度相同,您就要支付。价格是精确的。)


为了回应您的评论,您可以在与0“相邻”的
float
中精确表示的最大数字(因此0…数字都可以精确表示)是16777215(尾数=16777215,指数=0)和16777216(尾数=1,指数=24,因为它是1*2^24).16777217不能精确表示。16777218是。

不是每个
int
都可以表示为
float
。具体来说,如果
int
中设置的最高和最低位之间的位数大于
FLT\u MANT\u DIG-1
中定义的
float
(对于
double
DBL\u MANT\u DIG-1
)编译器警告您可能会丢失精度,因为
rand()
的声明意味着
rand()
可以返回任何
int
,包括那些不能表示为
float

gcc应该足够聪明,知道何时可以精确表示
int
文本:

float f= 1<<FLT_MANT_DIG; // yes
float g= (1<<FLT_MANT_DIG) - 1; // yes
float h= (1<<FLT_MANT_DIG) + 1; // no
float i= (1<<(FLT_MANT_DIG + 1)); // yes

float f=1这是否意味着
float f=123456789
将给出一个错误?它不会出错,但应该会给出一个警告。目前我面前没有GCC,但我刚刚在Visual Studio中测试了它,它给出了一个警告:
warning C4305:'initialization':从'int'截断为'float'
我发现我没有得到war除非我使用了
-Wconversion
选项,否则将禁用。
float f= 1<<FLT_MANT_DIG; // yes
float g= (1<<FLT_MANT_DIG) - 1; // yes
float h= (1<<FLT_MANT_DIG) + 1; // no
float i= (1<<(FLT_MANT_DIG + 1)); // yes