我遇到了一些问题,这让我疯了。
我有这样的代码
float a;
unsigned short b;
b += a;
当a
为负数时,b
正在使用香蕉。
我甚至做过演员
b += (unsigned short) a;
但它没有用。
我做错了什么?如何将float添加到unsigned short?
供参考: 当' a'是-1而b是0然后我会看到' b + = a'将给出b = 65535。
答案 0 :(得分:2)
通过显示您遇到问题的实际值,并解释您希望获得的价值,可以改善您的问题。
但与此同时,C11 6.3.1.4/1中浮动到整数转换的定义是:
当实数浮动类型的有限值被转换为除_Bool之外的整数类型时,小数部分被丢弃(即,该值被截断为零)。如果整数部分的值不能用整数类型表示,则行为是未定义的。
在b + a
float
的结果被分配回b
时,这一点开始发挥作用。回想一下b += a
等同于b = b + a
。
如果b + a
是-1
或更大幅度的负数,则其整数部分超出unsigned short
的范围,因此代码会导致undefined behaviour,这意味着任何事情都可以发生;包括但不限于去香蕉。
脚注重复浮点数不会先转换为有符号整数然后转换为unsigned short
:
当实数浮点类型的值转换为无符号类型时,无需执行将整数类型的值转换为无符号类型时执行的剩余操作。因此,便携式实际浮动值的范围是
(−1, Utype_MAX+1)
作为改进,你可以写:
b += (long long)a;
至少不会导致UB a > LLONG_MIN
。
答案 1 :(得分:2)
向float
添加unsigned short
的方法只是添加它,就像您完成的那样。添加的操作数将进行转换,我将在下面进行描述。
基于代码的一个简单示例是:
#include <stdio.h>
int main(void) {
float a = 7.5;
unsigned short b = 42;
b += a;
printf("b = %hu\n", b);
return 0;
}
毫不奇怪,输出是:
b = 49
声明
b += a;
相当于:
b = b + a;
(除了b
仅评估一次)。当添加(或减去,或......)不同类型的操作数时,它们会根据您在the C standard第6.3.1.8节中找到的一组规则转换为通用类型。在这种情况下,b
会从unsigned short
转换为float
。添加相当于42.0f + 7.5f
,产生49.5f
。然后,该分配会将此结果从float
转换为unsigned short, and the result,
49 is stored in
b`。
如果加法的数学结果超出float
(不太可能)的范围,或者它超出unsigned short
的范围(更有可能),那么程序将具有未定义的行为。您可能会在b
中看到存储的垃圾值,您的程序可能会崩溃,或者原则上确实会发生其他任何事情。将有符号或无符号整数转换为无符号整数类型时,结果将被包围;将浮点值转换为无符号类型时, not 会发生这种情况。
如果没有更多信息,就无法确定您实际遇到的问题或解决方法。
但似乎添加unsigned short
和float
并将结果存储在unsigned short
中似乎是不寻常的事情。在某些情况下,它可能正是您所需要的(如果是这样,您需要避免溢出),但您可能最好将结果存储在除{{{{{{{{{{{{{{{{{{{{{{{{{ 1}},也许在unsigned short
或float
中。 (顺便提一下,double
比double
更常用于浮点数据; float
主要用于在拥有 lot 数据时节省空间。 )
如果您正在进行数字转换,即使是隐式转换,它通常(但绝不总是)表明您应该首先使用不同类型的变量。
答案 2 :(得分:-1)
您正在观察被转换为整数的浮点数和无符号整数环绕(https://stackoverflow.com/a/9052112/1149664)的组合。
考虑
b += a
例如,对于a = -100.67
,您为已签名的数据类型添加了一个负值,并且根据b
的初始值,结果必须为负数。为什么你有想法使用未签名的短片而不只是float
或double
来执行此任务?
答案 3 :(得分:-1)
你希望b是正数(它是无符号的),但是a可以是负数。只要a不大于b就可以了。这是第一点。
第二 - 当你输出负值以取消签名时......实际上结果应该是什么?数字符号存储在最高有效位中,对于负数值,它为1.当值为无符号时,如果最高有效位为1,则该值非常高并且与负数值没有任何共同点。
也许尝试b - = fabs(a)表示否定a。这不是你想要的吗?