C和C++标准对位级整数表示和操作有何看法?

Cor*_*lks 18 c c++ integer data-representation language-lawyer

我知道C和C++标准没有规定数字的特定表示(可以是二进制补码,符号和数量等).但我不清楚这些标准(并且无法确定是否已经说明)知道在使用位时是否存在任何特定的限制/保证/保留表示.尤其:

  1. 如果整数类型中的所有位都为零,那么整数整数是否代表零?
  2. 如果整数类型中的任何位是1,那么整数整数是否表示非零?(如果这是"是",那么一些表示如符号和幅度将受到额外限制)
  3. 是否有保证的方法来检查是否有任何位未设置?
  4. 是否有保证的方法来检查是否设置了任何位?(#3和#4类型取决于#1和#2,因为我知道如何设置,例如某个变量中的第5位(参见#5)x,我想检查变量y以查看它是否是第5位是1,我想知道是否if (x & y)可行(因为据我所知,这取决于表示的值而不是该位是否实际上是1或0))
  5. 是否有保证的方法来设置最左边和/或最右边的位?(至少比将char c所有位置为真(设置为c = c | ~c)并c = c << (CHAR_BIT - 1)设置高位和c = c ^ (c << 1)低位更简单的方法,假设我没有做任何假设,我不应该这样,给出这些问题)
  6. 如果#1的答案是"否",那么如何迭代整数类型的位并检查每个位是1还是0?

我想我的整体问题是:C和C++标准是否有关于位和整数的限制/保证/保留表示,尽管事实上没有强制表示整数的表示(如果C和C++标准在这方面有所不同) ,他们的区别是什么?)

我在完成作业时提出了这些问题,这需要我做一些操作(注意这些不是我作业的问题,这些都是"抽象的").

编辑:至于我称之为"位",我的意思是"值形成"位而不包括"填充"位.

Joh*_*eek 15

(1)如果整数类型中的所有位都为零,则整数整数是否为零?

是的,由全零组成的位模式始终表示0:

整数类型的表示应使用纯二进制计算系统定义值.49 [§3.9.1/ 7]

49使用二进制数字0和1的整数的位置表示,其中由连续位表示的值是加法的,以1开始,并且乘以2的连续积分幂,除了可能对于具有最高位置的位.


(2)如果整数类型中的任何位是1,那么整数整数是否表示非零?(如果这是"是",那么一些表示如符号和幅度将受到额外限制)

实际上,特别允许签名幅度:

[ 例如:本国际标准允许积分类型的2的补码,1的补码和带符号的幅度表示.- 示例 ] [§3.9.1/ 7]


(3)是否有保证的方法来检查是否未设置任何位?

如果考虑签名类型,我相信答案就是"不".它相当于使用所有1的位模式进行相等测试,这只有在您能够生成具有所有1的位模式的带符号数的情况下才有可能.对于无符号数,此表示是有保证的,但如果数字不可表示,则从unsigned转换为signed是未定义的:

如果目标类型已签名,则如果可以在目标类型(和位字段宽度)中表示该值,则该值不会更改; 否则,该值是实现定义的.[§4.7/ 3]


(4)是否有保证检查是否设置了位的方法?

我不这么认为,因为允许有符号幅度-0将比较等于-0.但是应该可以使用无符号数字.


(5)是否有保证的方法来设置最左边和/或最右边的位?

同样,我认为对于无符号数字,答案是"是",对于有符号数字,答案是"否".对于带负号的数字,未定义班次:

否则,如果E1有一个带符号的类型和非负值,并且在结果类型中可以表示E1×2 E2,那么这就是结果值; 否则,行为未定义.[§5.8/ 2]

  • "是的,由全零组成的位模式总是代表0" - 这不是引用的文本.从C99开始,如果整数类型具有填充位,则所有位零可能是陷阱表示.C11增加了一个明确的要求:"对于任何整数类型,所有位为零的对象表示应该是该类型中零值的表示." (3认同)

AnT*_*AnT 8

您反复使用术语"所有位",但您没有说明您所指的"所有位".C/C++中整数类型的对象表示可能包括值形成位填充位.唯一保证不具有填充位的整数类型是[signed/unsigned] char.

语言总是保证如果所有的值形成位都为零,则表示的整数值也为零.

至于填充位,事情有点复杂.C语言的原始规范(C89/90以及原始C99)并不保证将所有对象位设置为零都会产生有效的整数表示.它可能会产生无效的陷阱表示.即在原始C(甚至在C99中)使用memset(..., 0, ...)整数类型并不保证对象将接收有效的零值(除了[signed/unsigned] char).这在后来的规范中有所改变,即在C99的技术勘误之一中.现在要求整数对象中的全零位模式(涉及所有位,包括填充的位)表示有效的零值.

即在现代C中,使用memset(..., 0, ...)将任何整数对象设置为零是合法的,但它仅在C99之后变得合法.