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

时间:2022-04-11 05:31:01

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

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

#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.

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

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

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

3 个解决方案

#1


14  

GCC emits this warning when a loss of precision may result from the cast. (in other words, the value may be "altered")

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

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.

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

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

在第二种情况下,100可以安全地铸造到浮子上而没有任何精度损失。

#2


5  

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).

为Mysticial写的东西添加一些东西(这是正确的):你的C实现使用32位IEEE 754单精度二进制浮点的浮点数和32位的int。在“your”int中,您可以拥有31位数字和1位符号。在“你的”浮点数中,尾数是24位,有1位符号。显然,需要超过24位加上符号的整数不能完全转换为“你的”浮点数。 (我使用“你的”代表你的编译器,你正在使用的编译器.C标准没有告诉float或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.

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

(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.)

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

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.

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

#3


0  

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.

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

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

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 should spit out a warning for initializing h only.

gcc应该吐出警告来初始化h。

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.

顺便提一下,如果RAND_MAX小于或等于(1 << FLT_MANT_DIG) - 1,你可以安全地将rand()分配给一个浮点数,即使编译器向你抱怨也是如此。

#1


14  

GCC emits this warning when a loss of precision may result from the cast. (in other words, the value may be "altered")

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

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.

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

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

在第二种情况下,100可以安全地铸造到浮子上而没有任何精度损失。

#2


5  

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).

为Mysticial写的东西添加一些东西(这是正确的):你的C实现使用32位IEEE 754单精度二进制浮点的浮点数和32位的int。在“your”int中,您可以拥有31位数字和1位符号。在“你的”浮点数中,尾数是24位,有1位符号。显然,需要超过24位加上符号的整数不能完全转换为“你的”浮点数。 (我使用“你的”代表你的编译器,你正在使用的编译器.C标准没有告诉float或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.

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

(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.)

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

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.

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

#3


0  

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.

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

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

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 should spit out a warning for initializing h only.

gcc应该吐出警告来初始化h。

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.

顺便提一下,如果RAND_MAX小于或等于(1 << FLT_MANT_DIG) - 1,你可以安全地将rand()分配给一个浮点数,即使编译器向你抱怨也是如此。