为什么GCC警告这种隐式转换?

时间:2011-10-12 04:47:22

标签: c gcc type-conversion compiler-warnings

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

#include <stdlib.h>
float square = rand();

但是,以下内容不会产生任何警告:

float square = 100;

海湾合作委员会发出的警告如下:

tests/ChemTests.cpp:17:23: error: conversion to ‘float’ from ‘int’ may alter its value

我不明白为什么前者会发出警告,因为rand()已正确声明并返回int,就像100整数字一样。

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

3 个答案:

答案 0 :(得分:14)

当演员阵容导致精度下降时,GCC会发出此警告。 (换句话说,价值可能会“改变”)

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

在第二种情况下,100可以安全地转换为float而不会有任何精确损失。

答案 1 :(得分:5)

为Mysticial写的内容添加一些内容(这是正确的):您的C实现使用32 bits IEEE 754 single precision binary floating-pointfloat为32位的int。在“您的”int中,您可以拥有31位数字和1位符号。在“你的”浮点数中,mantissa是24位,并且有1位符号。显然,int s需要超过24位加号才能被表示,不能完全转换为“你的”float。 (我使用“你的”代表你的编译器,你正在使用的编译器.C标准没有说明floatint的确切长度。

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

(即使没有准确解释浮点如何工作,你的int是32位并且“仅支持”整数。你的float是32位并且“支持”浮点数。显然浮点数数字更难以表示(您必须保存小数点所在的地方),因此如果intfloat的长度相同,则必须支付“价格”。价格为精度。)

要回复您所做的评论,您可以在float中准确表示的最大数字是“连续”为0(因此0 ...数字都可以完全表示)是16777215(具有尾数= 16777215和指数= 0)和16777216(尾数= 1且指数= 24,因为它是1 * 2 ^ 24)。 16777217无法准确描述。 16777218是。

答案 2 :(得分:0)

并非每个int都可以表示为float。具体来说,如果int中设置的最高位和最低位之间的位数大于FLT_MANT_DIG - 1中定义的<float.h>,则无法将其精确表示为float 。 (同样适用于doubleDBL_MANT_DIG - 1。)编译器警告您可能会丢失精度,因为rand()的声明意味着rand()可以返回任何{{1} },包括那些无法表示为int的内容。

gcc应该足够聪明,知道何时可以准确表示float文字:

int

gcc应该发出警告,仅初始化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

顺便说一句,如果h小于或等于RAND_MAX,即使编译器向您抱怨,也可以安全地将(1<<FLT_MANT_DIG) - 1分配给rand()