将-1转换为无符号类型

par*_*mar 9 c++

请考虑以下代码来设置x的所有位

unsigned int x = -1;
Run Code Online (Sandbox Code Playgroud)

这是便携式吗?它似乎至少适用于Visual Studio 2005-2010

Pub*_*bby 6

显然它是:

(4.7)如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模2 n,其中n是用于表示无符号类型的位数).[注意:在二进制补码表示中,此转换是概念性的,并且位模式没有变化(如果没有截断).

由于模数的属性,它保证是该类型可能的最大量.

C99还允许它:

否则,如果newtype是无符号的,则通过重复地添加或减去一个可以在newtype中表示的最大值来转换该值,直到该值在newtype的范围内.49)

哪个也是最大可能的数量.


可能的最大量可能不是所有位设置.使用~static_cast<unsigned int>(0)了点.

  • @Pubby:根据C99标准,在任何情况下``(unsigned something)-1`都不同于`〜(unsigned something)0`.所以`-1`是*总是*所有位设置.参见C99的§6.5.3.3,"如果提升的类型是无符号类型,则表达式"~E`等效于该类型中可表示的最大值减去"E". (3认同)

Die*_*Epp 6

引用重的答案:

我知道这里有很多正确的答案,但我想补充一些引用.我将引用两个标准:C99 n1256草案(免费提供)和C++ n1905草案(也可免费提供).这些特定标准并没有什么特别之处,它们只是免费提供,而且目前最容易找到.

C++版本:

§5.3.29:根据本段~(type)0,如果(type)是无符号类型,则保证该值设置所有位.

〜的操作数应具有整数或枚举类型; 结果是其操作数的一个补码.执行整体促销.结果的类型是提升的操作数的类型.

§3.9.14:这解释了溢出如何与无符号数一起使用.

声明无符号的无符号整数应遵守算术模2 n的定律,其中n是该特定整数大小的值表示中的位数.

§3.9.17,加脚注49:这解释了数字必须是二进制的.由此,我们可以推断出~(type)0必须是可表示的最大数字type(因为它打开了所有位,并且每个位都是相加的).

积分类型的表示应通过使用纯二进制计算系统49来定义值.

49)使用二进制数字0和1的整数的位置表示,其中由连续位表示的值是加法的,以1开始,并且乘以2的连续积分幂,除了可能对于具有最高位置的位.(改编自美国国家信息处理系统词典.)

由于算术是以2 n为模进行的,因此可以保证它(type)-1是该类型中可表示的最大值.它也保证~(type)0是该类型中可表示的最大值.因此,它们必须是平等的.

C99版本:

C99版本以更加紧凑,明确的方式拼出它.

§6.5.33:

〜运算符的结果是其(提升的)操作数的按位补码(即,当且仅当未设置转换后的操作数中的相应位时,才会设置结果中的每个位).整数提升在操作数上执行,结果具有提升类型.如果提升类型是无符号类型,则表达式~E等于该类型中可表示的最大值减去E.

与在C++中一样,无符号算法保证是模块化的(我认为我现在已经完成了足够的标准挖掘),因此C99标准绝对保证~(type)0 == (type)-1,我们从§6.5.33中知道~(type)0必须设置所有位.

摘要:

是的,它是便携式的. unsigned type x = -1;保证根据标准设置所有位.

脚注:是的,我们讨论的是值位而不是填充位.但是,我怀疑你需要将填充位设置为1.您可以从最近的Stack Overflow问题(链接)中看到,GCC被移植到PDP-10,其中long long类型具有单个填充位.在这样的系统上,unsigned long long x = -1;可能不会将该填充位设置为1.但是,如果使用指针转换,您将只能发现这一点,而这通常不是可移植的.


Kei*_*son 5

我在阅读这个问题时很草率,并提出了一些可能因此而误导的评论.我会试着澄清这个答案中的困惑.

声明

unsigned int x = -1;
Run Code Online (Sandbox Code Playgroud)

保证设置xUINT_MAX类型的最大值unsigned int.表达式-1是类型int,并且它被隐式转换为unsigned int.转换(根据值定义,而不是表示)导致目标无符号类型的最大值.

(碰巧的是,转换的语义针对二进制补码系统进行了优化;对于其他方案,转换可能涉及的不仅仅是复制位.)

但问题是设置所有位x.那么,是否UINT_MAX表示为全比特一?

对于有符号整数有几种可能的表示(二进制补码是最常见的,但是一些补码和符号和幅度也是可能的).但是,我们正在处理的无符号整数类型,这样的方式签署整数表示是无关紧要的.

无符号整数需要以纯二进制格式表示.假设表示的所有位都对unsigned int对象的值有贡献,那么是的,UINT_MAX必须表示为all-bits-one.

另一方面,允许整数类型具有填充位,这些位对表示没有贡献.例如,unsigned int32位是合法的,但是这些位中只有24位是值位,所以UINT_MAX2*24-1而不是2*32-1.所以在最一般的情况下,你可以说的就是那个

unsigned int x = -1;
Run Code Online (Sandbox Code Playgroud)

将所有位设置x为1.

实际上,很少有系统具有整数类型的填充位.因此,在绝大多数系统中,unsigned int大小为N位,最大值为2**N-1,上述声明所有位设置x为1.

这个:

unsigned int x = ~0U;
Run Code Online (Sandbox Code Playgroud)

也将设置x为UINT_MAX,因为无符号类型的按位补码是根据减法定义的.