为什么GCC会对这种隐式转换发出警告?
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
#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