我有一个unsigned int实际存储一个signed int,而signed int的范围是-128到127.
我想将这个值存储回unsigned int中,这样我就可以了 应用掩码0xFF并获取签名字符。
如何进行转换?
即
unsigned int foo = -100;
foo = (char)foo;
char bar = foo & 0xFF;
assert(bar == -100);
答案 0 :(得分:2)
& 0xFF
操作将生成0
到255
范围内的值。以这种方式获得负数是不可能的。因此,即使您在某处使用& 0xFF
,您仍需要稍后应用转化才能达到-128
到127
的范围。
在您的代码中:
char bar = foo & 0xFF;
隐式转换为char
。这依赖于实现定义的行为,但这将适用于除了最深奥的系统之外的所有系统。最常见的实现定义是将unsigned char
转换为char
时适用的转换的反转。
(应删除您之前的第foo = (char)foo;
行。)
然而,
char bar = foo;
会产生完全相同的效果(再次,除了那些深奥的系统)。
答案 1 :(得分:1)
由于unsigned int foo
值未达到-128
或127
的边界,因此隐式转换适用于此情况。但是如果unsigned int foo
具有更大的值,那么在将其存储在char
变量中时,您将丢失字节,并且会在您的程序中获得意外结果。
答案 2 :(得分:1)
回答C,
如果您的unsigned int
的值是通过赋值类型char
(其中char
恰好是签名类型)或类型signed char
的值来设置的,如果指定的值为负,则存储的值是指定负值的算术和,而不是UINT_MAX
。这将远远超出(签名)char
在我遇到过的任何C系统上可表示的值范围。如果将该值转换回(带符号)char
,无论是隐式地还是通过强制转换,"结果是实现定义的,或者是实现定义的信号被引发" (C2011,6.3.1.3/3)。
以避免实现定义的行为的方式转换回原始char
值有点棘手(但依赖于实现定义的行为可能提供更容易的方法)。当然,屏蔽除8个最低位值之外的所有位都不起作用,因为它总是给你一个正值。此外,它假设char
是8位宽,原则上不保证。它不一定能给你正确的位模式,因为C允许以三种不同的方式表示负整数。
这是一种适用于任何符合要求的C系统的方法:
unsigned int foo = SOME_SIGNED_CHAR_VALUE;
signed char bar;
/* ... */
if (foo <= SCHAR_MAX) {
/* foo's value is representable as a signed char */
bar = foo;
} else {
/* mask off the highest-order value bits to yield a value that fits in an int */
int foo2 = foo & INT_MAX;
/* reverse the conversion to unsigned int, as if unsigned int had the same
number of value bits as int; the other bits are already accounted for */
bar = (foo2 - INT_MAX) - 1;
}
它仅依赖于C本身定义的整数表示和转换的特性。
答案 3 :(得分:0)
投射到较小的尺寸可能会截断该值。从签名到无符号或相反的转换可能会导致错误的值(例如255 - > -1)。
如果必须使用不同的数据类型进行计算,请选择一种常见类型,优先使用signed和long int(32位),并在逐渐减小之前检查边界(更小的尺寸)。
Signed帮助您检测下溢(例如,当结果小于0时),long int(或简单地说:int,这意味着自然字长)适合机器(32位或64位),并且它#39 ;对于大多数目的来说,它足够大。
还要尽量避免公式中的混合类型,特别是当它们包含除法(/)。
时