为什么 GCC 对这种隐式转换发出警告?
GCC 警告我以下代码包含可能更改值的隐式转换:
#include <stdlib.h>
float square = rand();
但是,以下内容不会产生任何警告:
float square = 100;
GCC 给出的警告如下:
tests/ChemTests.cpp:17:23: error: conversion to ‘float’ from ‘int’ may alter its value
我不明白为什么前者会发出警告,因为 rand()
已正确声明并返回 int
,就像 100
整数文字一样。
为什么第一行会给出编译器警告,而第二行则不会,即使两者都有从 int
到 float
的隐式转换?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当转换可能导致精度损失时,GCC 会发出此警告。 (换句话说,该值可能会被“更改”)
在第一种情况下,
rand()
返回一个int
。由于并非所有可以存储在int
中的值都可以表示为float
,因此它将发出此警告。在第二种情况下,100 可以安全地转换为浮点型,而不会损失任何精度。
GCC emits this warning when a loss of precision may result from the cast. (in other words, the value may be "altered")
In the first case,
rand()
returns anint
. Since not all values that can be stored in anint
are representable as afloat
, it will emit this warning.In the second case, 100 can be safely casted to a
float
without any precision loss.要在 Mysticial 所写的内容中添加一些内容(这是正确的):您的 C 实现使用
float
,它们是 32位IEEE 754单精度二进制浮点和32位的int
。在“your”int
中,您可以有 31 位数字和 1 位符号。在“your”浮点数中,尾数为 24 位,符号位为 1 位。显然,需要超过 24 位加号来表示的int
无法完全转换为“您的”float
。 (我使用“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 是。To add something to what Mysticial wrote (that is correct): your implementation of C uses
float
that are 32 bits IEEE 754 single precision binary floating-point andint
that are 32 bits. In "your"int
you can have 31 bits of number and 1 bit of sign. In "your" float themantissa
is 24 bits and there is 1 bit of sign. Clearlyint
s that need more than 24 bits plus sign to be represented can't be converted exactly to "your"float
. (I use the "your" to represent "your" compiler, the compiler you are using. The C standard doesn't tell the exact length offloat
orint
).Now, the
rand()
can generate anyint
number, so the compiler has to give you the warning. The100
is a numeric literal that is known at compile time, so the compiler can statically check if that number is convertible.(even without explaining exactly how floating points work, your
int
is 32 bits and "supports" only integer numbers. Yourfloat
is 32 bits and "supports" floating point numbers. Clearly floating point numbers are more difficult to represent (you have to save somewhere where the decimal point is), so there must be a "price" you pay if bothint
andfloat
have the same length. The price is precision.)To respond to the comment you made, the maximum number you can represent exactly in a
float
that is "contiguous" to 0 (so that 0...number are all exactly representable) are 16777215 (that has mantissa = 16777215 and exponent = 0) and 16777216 (that has mantissa = 1 and exponent = 24, because it's 1 * 2 ^ 24). 16777217 isn't representable exactly. 16777218 is.并非每个< 中定义的
int
都可以表示为float
。具体来说,如果int
中设置的最高位和最低位之间的位数大于FLT_MANT_DIG - 1
/code>,它不能精确地表示为float
。 (double
和DBL_MANT_DIG - 1
也是如此。)编译器会警告您,由于rand()
的声明,可能会导致精度损失。意味着rand()
可以返回任何int
,包括那些不能表示为float
的。gcc 应该足够聪明,知道何时可以精确表示
int
文字:gcc 应该仅针对初始化
h
发出警告。顺便说一句,如果
RAND_MAX
小于或等于(1<,您可以安全地将
rand()
分配给float
,即使编译器向您抱怨。Not every
int
can be represented as afloat
. Specifically, if the number of bits between the highest and lowest bit set in anint
is greater thanFLT_MANT_DIG - 1
, defined in<float.h>
, it cannot be represented precisely as afloat
. (Same goes fordouble
andDBL_MANT_DIG - 1
.) The compiler warns you that there's a potential loss of precision because the declaration ofrand()
means thatrand()
could return anyint
, including those that cannot be represented as afloat
.gcc should be smart enough to know when
int
literals can be represented precisely:gcc should spit out a warning for initializing
h
only.Incidentally, if
RAND_MAX
is less than or equal to(1<<FLT_MANT_DIG) - 1
, you can safely assignrand()
to afloat
, even if the compiler complains to you.