将双精度浮点数转换为无符号整数/字符。

7

我在这里阅读到(此处):

根据C99 §6.3.1.4脚注50的规定:

当整数类型的值转换为无符号类型时所执行的取余操作,在将实浮点类型的值转换为无符号类型时不需要执行。因此,可移植实浮点值的范围为(-1,Utype_MAX+1)。

现在,我对以下内容感兴趣(这次针对的是C++ 03!):

double d1 = 257;
double d2 = -2;

unsigned char c1 = d1; // undefined, since d1 > 256
unsigned char c2 = d2; // undefined, since d2 < -1

并且

double d1 = 257;
double d2 = -2;

unsigned int i1 = d1; // defined, since d1 <= 2^32
unsigned int i2 = d2; // still undefined, right?

unsigned char c1 = i1; // defined, modulo 2^8, so c1 == 1

那么第一个c1和第二个c1不能保证比较相等,对吗?上面的引用是否也适用于C++03,还是有其他规则?

编辑:

为了使c2定义(对于-(2^31-1) <= d2 < 0),这样做是必要的吗?

double d2 = -2;
int sign = (d2<0 ? -1 : 1);

unsigned char c2 = sign * (int)abs(d2); // defined, c2 == 2^8-2 ?
1个回答

2
是的,同样的规则也适用于C++。(但是,我参考的是2010年的C++标准草案;C++ 2003已经过时了。此外,我使用的是N3092,而不是官方草案。)第4.9条第1段规定:“如果截断的值不能在目标类型中表示,则其行为未定义。”
无符号整数运算会进行取模运算;这个运算会对类型的最大值加1进行取模。然而,这只适用于类型内部的运算。从浮点数转换为无符号整数不属于这种情况。
您用于转换d2的代码似乎比必要的复杂。如果d2在int范围内,您可以简单地使用unsigned char c2 = (int) d2;。(尽管从int转换为unsigned int也不属于同类的无符号整数运算,但是该转换的规范确实说它被降低到与无符号整数算术相同的方式。)

顺便提一下,这个措辞也在 [C++11: 4.9/1] 中完全相同(也在 n3690 中找到,那是去年五月的 C++1y 草案)。 - Lightness Races in Orbit
感谢回答。将 int 转换为 unsigned int 时,没有任何位重新排列的过程,对吧?而当 unsigned int 转换为 unsigned char 时,始终会丢弃高位比特,对吧?那么,如果 dchar 的范围内(例如 -2),则 unsigned char ca = (char)dunsigned char cb = (int)d 总是相等的,对吧? - mb84
关于“int”位布局,很少有保证,因为1s补码甚至可能是合法的(不确定,但在实际应用中影响很小)。 - Yakk - Adam Nevraumont

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接