在保留原始位模式的同时,如何将(int)转换为(unsigned int)? [英] How can an (int) be converted to (unsigned int) while preserving the original bit pattern?

查看:83
本文介绍了在保留原始位模式的同时,如何将(int)转换为(unsigned int)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们定义:

short x = -1;
unsigned short y = (unsigned short) x;

根据C99标准:

否则,如果新类型是无符号的,则将值转换为重复加或减一个比最大值大一倍的值可以用新类型表示,直到该值在新类型.(ISO/IEC 9899:1999 6.3.1.3/2)

Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type. (ISO/IEC 9899:1999 6.3.1.3/2)

因此,假设 short 的两个字节和二进制补码的表示形式,这两个整数的位模式为:

So, assuming two bytes for short and a two's complement representation, the bit patterns of these two integers are:

x = 1111 1111 1111 1111 (value of -1),
y = 1111 1111 1111 1111 (value of 65535).

由于-1不在 unsigned short 的值范围内,并且可以在 unsigned short 中表示的最大值为65535,所以65536被添加到-1可以得到65535,该值在 unsigned short 范围内.因此,尽管表示的值已更改,但从 int 转换为 unsigned 时,这些位保持不变.

Since -1 is not in the value range for unsigned short, and the maximum value that can be represented in an unsigned short is 65535, 65536 is added to -1 to get 65535, which is in the range of unsigned short. Thus the bits remain unchanged in casting from int to unsigned, though the represented value is changed.

但是,该标准还说,表示形式可以是两个的补码,一个的补码或符号和大小.其中哪些适用于实现定义,....."(ISO/IEC 9899:1999 6.2.6.2/2)

But, the standard also says that representations may be two's complement, one's complement, or sign and magnitude. "Which of these applies is implementation-defined,...." (ISO/IEC 9899:1999 6.2.6.2/2)

在使用补码的系统上, x 在转换之前将表示为 1111 1111 1111 1110 ,在使用符号和大小表示的系统上, x表示为 1000 0000 0000 0001 .这两个位模式都表示一个值-1,该值不在 unsigned short 的值范围内,因此在每种情况下,都将65536添加到-1以使这些值进入范围.强制转换后,这两个位模式均为 1111 1111 1111 1111 .

On a system using one's complement, x would be represented as 1111 1111 1111 1110 before casting, and on a system using sign and magnitude representation, x would be represented as 1000 0000 0000 0001. Both of these bit patterns represent a value of -1, which is not in the value range of unsigned short, so 65536 would be added to -1 in each case to bring the values into range. After the cast, both of these bit patterns would be 1111 1111 1111 1111.

因此,从 int 转换为 unsigned int 时保留位模式取决于实现.

So, preservation of the bit pattern in casting from int to unsigned int is implementation dependent.

在保留位模式的同时,将 int 转换为 unsigned int 的功能似乎是对负数进行位移位操作的便捷工具,并且我已经看到它被倡导为一种技术.但是似乎无法保证该技术可以按标准使用.

It seems like the ability to cast an int to unsigned int while preserving the bit pattern would be a handy tool for doing bit-shifting operations on negative numbers, and I have seen it advocated as a technique for just that. But this technique does not appear to be guaranteed to work by the standard.

我是在这里正确阅读标准吗?还是我误解了有关从有符号类型转换为无符号类型的详细信息?2的补码实现是否足够普遍,以至于从 int 转换为 unsigned 的位模式保留假设是合理的?如果不是,是否存在更好的方法来保留从 int unsigned int 的转换下的位模式?

Am I reading the standard correctly here, or am I misunderstanding something about the details of the conversion from signed to unsigned types? Are two's complement implementations prevalent enough that the assumption of bit-pattern preservation under casting from int to unsigned is reasonable? If not, is there a better way to preserve bit patterns under a conversion from int to unsigned int?

我的最初目标是找到一种方法,以保留位模式的方式将 int 强制转换为 unsigned int .我当时认为将 int 转换为 int N _t 可以帮助实现这一目标:

My original goal was to find a way to cast an int to unsigned int in such a way that the bit pattern is preserved. I was thinking that a cast from int to intN_t could help accomplish this:

unsigned short y = (unsigned short)(int16_t) x;

但是这个想法当然是错误的!充其量只能在强制转换为 unsigned 之前强制执行二进制补码表示,以便最终的位模式将是二进制补码.我很想删除问题,但是我仍然对将 int 转换为保留位模式的 unsigned int 的方法感兴趣,@ Leushenko提供了一个非常整洁的方法用工会解决这个问题.但是,我更改了问题的标题以反映最初的意图,并编辑了结尾的问题.

but of course this idea was wrong! At best this would only enforce two's complement representation before casting to unsigned, so that the final bit pattern would be two's complement. I am tempted to just delete the question, yet I am still interested in ways to cast from int to unsigned int that preserve bit patterns, and @Leushenko has provided a really neat solution to this problem using unions. But, I have changed the title of the question to reflect the original intention, and I have edited the closing questions.

推荐答案

(int)转换为(unsigned)(intN_t)以保留位模式是否可以接受?

Is it acceptable to cast from (int) to (unsigned)(intN_t) to preserve bit patterns?

通常,是的,但没有在C中为所有值指定这样做.C会尝试在类型转换过程中保持值,而不是位模式.

Often, yes, but not specified to do so in C for all values. C tries to maintain values during type conversions, not bit patterns.

(例如 x )应表示为 int unsigned 和所选的intN_t ,则该值的位模式不变.因此,问题与 x 为负时有关.

Should a value, say x, be representable as int, unsigned and the chosen intN_t, then that value's bit pattern does not change. So the question relates to when x is negative.

C通过将无符号类型的最大值+ 1"加/减到结果在范围内,来指定转换为任何无符号类型以应对溢出.如果有符号类型使用2的补码编码,则较低有效位的模式将与目标无符号类型匹配.

C specifies that conversion to any unsigned type cope with overflow by add/subtracting the "maximum value of the unsigned type + 1" until the result is in range. Should the signed type use 2's complement encoding, the pattern of lower significant bits will match the target unsigned type.

在实现定义的行为中转换为有符号整数类型-因此,OP陷入了困境.

Conversion to signed integer types in implementation defined behavior - hence OP's dilemma.

C仅指定有符号整数类型的范围及其对应的无符号整数类型都需要编码范围: 0 至最大有符号类型.允许IOW INT_MAX == UINT_MAX .在这种罕见的平台上,从 int 转换为 unsigned int 会丢失符号.

C only specifies that the range of a signed integer type and its corresponding unsigned integer type both need to encode the rage: 0 to the signed type maximum. IOWs INT_MAX == UINT_MAX is allowed. On such rare platforms, converting from int to unsigned to int loses the sign.

如果代码需要保留某些带符号类型的位模式,则在所有情况下都可以使用带 unsigned char 数组的 union .

If code needs to preserve some signed type's bit pattern, a union with an array of unsigned char works in all cases.

union uA {
  some_signed_int_type i;
  unsigned char uc[sizeof (some_signed_int_type)];
}

具有固定宽度的无符号类型(这些类型为可选)的并集,其最大值大于有符号最大值,用于维护位模式.即使正值也不要依赖于相同的值.固定宽度类型没有填充,普通的带符号类型没有填充.

A union with a fixed-width unsigned type (these types are optional) whose maximum is greater than the signed maximum works to maintain the bit pattern. Do not rely on the value being the same, even for positive values. Fixed width types do not have padding, not so the general signed types.

assert(uintN_MAX > some_signed_type_max);
union uB {
  some_signed_int_type i;
  uintN_t u;
}

无符号字符(u)intN_t 的主要好处是指定了这些类型没有填充.

The central benefit of unsigned char and (u)intN_t is that these types are specified to not have padding.

这篇关于在保留原始位模式的同时,如何将(int)转换为(unsigned int)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆