将signed char存储在unsigned int中

时间:2016-01-06 20:23:00

标签: c data-conversion

我有一个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);

4 个答案:

答案 0 :(得分:2)

& 0xFF操作将生成0255范围内的值。以这种方式获得负数是不可能的。因此,即使您在某处使用& 0xFF,您仍需要稍后应用转化才能达到-128127的范围。

在您的代码中:

char bar = foo & 0xFF;

隐式转换为char。这依赖于实现定义的行为,但这将适用于除了最深奥的系统之外的所有系统。最常见的实现定义是将unsigned char转换为char时适用的转换的反转。

(应删除您之前的第foo = (char)foo;行。)

然而,

char bar = foo;

会产生完全相同的效果(再次,除了那些深奥的系统)。

答案 1 :(得分:1)

由于unsigned int foo值未达到-128127的边界,因此隐式转换适用于此情况。但是如果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 ;对于大多数目的来说,它足够大。

还要尽量避免公式中的混合类型,特别是当它们包含除法(/)。