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

发布于 2024-12-09 09:14:50 字数 514 浏览 0 评论 0 原文

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 整数文字一样。

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

GCC warns me that the following piece of code contains an implicit conversion that may change a value:

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

However, the following does not yield any warning:

float square = 100;

The warning given by GCC is a follows:

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

I don't understand why the former would give a warning, since rand() is properly declared and returns an int, just as the 100 integer literal.

Why does the first line give a compiler warning but not the second, even though both have an implicit conversion from intto float?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

中二柚 2024-12-16 09:14:50

当转换可能导致精度损失时,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 an int. Since not all values that can be stored in an int are representable as a float, it will emit this warning.

In the second case, 100 can be safely casted to a float without any precision loss.

合久必婚 2024-12-16 09:14:50

要在 Mysticial 所写的内容中添加一些内容(这是正确的):您的 C 实现使用 float ,它们是 32位IEEE 754单精度二进制浮点和32位的int。在“your”int 中,您可以有 31 位数字和 1 位符号。在“your”浮点数中,尾数为 24 位,符号位为 1 位。显然,需要超过 24 位加号来表示的 int 无法完全转换为“您的”float。 (我使用“your”来表示“你的”编译器,即你正在使用的编译器。C 标准没有告诉 floatint 的确切长度)。

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

(即使没有准确解释浮点如何工作,您的 int 是 32 位并且仅“支持”整数。您的 float 是 32 位并且“支持”浮点数。显然,浮点数更难表示(您必须保存小数点所在的位置),因此如果 intfloat 都需要付出“代价” > 具有相同的长度。精度。)

为了回应您所做的评论,您可以在“连续”到 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 and int that are 32 bits. In "your" int you can have 31 bits of number and 1 bit of sign. In "your" float the mantissa is 24 bits and there is 1 bit of sign. Clearly ints 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 of float or int).

Now, the rand() can generate any int number, so the compiler has to give you the warning. The 100 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. Your float 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 both int and float 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.

油焖大侠 2024-12-16 09:14:50

并非每个 int 都可以表示为 float。具体来说,如果 int 中设置的最高位和最低位之间的位数大于 < 中定义的 FLT_MANT_DIG - 1 /code>,它不能精确地表示为float。 (doubleDBL_MANT_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

gcc 应该仅针对初始化 h 发出警告。

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

Not every int can be represented as a float. Specifically, if the number of bits between the highest and lowest bit set in an int is greater than FLT_MANT_DIG - 1, defined in <float.h>, it cannot be represented precisely as a float. (Same goes for double and DBL_MANT_DIG - 1.) The compiler warns you that there's a potential loss of precision because the declaration of rand() means that rand() could return any int, including those that cannot be represented as a float.

gcc should be smart enough to know when int literals can be represented precisely:

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

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 assign rand() to a float, even if the compiler complains to you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文