20

我知道 C 和 C++ 标准没有规定数字的特定表示(可能是二进制补码、符号和大小等)。但是我不太了解标准(并且无法找到是否已说明),无法知道在使用位时是否有任何特定的限制/保证/保留表示。特别:

  1. 如果整数类型中的所有位都为零,那么整个整数是否代表零?
  2. 如果整数类型中的任何一位为 1,那么整数作为一个整体是否表示非零?(如果这是“是”,那么像符号和大小这样的一些表示将受到额外限制)
  3. 是否有保证的方法来检查是否未设置任何位?
  4. 是否有保证的方法来检查是否设置了任何位?(#3 和#4 取决于#1 和#2,因为我知道如何设置,例如某个变量中的第 5 位(参见 #5)x,我想检查一个变量y以查看它是否是第 5 位是 1,我想知道是否if (x & y)可行(因为据我了解,这取决于表示的值,而不是该位实际上是 1 还是 0))
  5. 是否有保证的方法来设置最左边和/或最右边的位?(至少比采用 a所有位为char c真(由c = c | ~cc = c << (CHAR_BIT - 1)c = c ^ (c << 1)
  6. 如果#1 的答案是“否”,如何遍历整数类型的位并检查每个位是 1 还是 0?

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

我在做作业时提出了这些问题,这需要我做一些操作(注意这些不是我作业中的问题,这些问题更加“抽象”)。

编辑:至于我所说的“位”,我的意思是“价值形成”位,不包括“填充”位。

4

8 回答 8

16

(1)如果一个整数类型中的所有位都为零,那么整个整数是否代表零?

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

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

49整数的位置表示,使用二进制数字 0 和 1,其中由连续位表示的值是相加的,从 1 开始,并乘以 2 的连续整数幂,可能最高位置的位除外。


(2)如果整数类型中的任何一位为1,那么整数作为一个整体是否表示非零?(如果这是“是”,那么像符号和大小这样的一些表示将受到额外限制)

不,事实上,有符号的幅度是特别允许的:

[示例:本国际标准允许整数类型的 2 的补码、1 的补码和有符号幅度表示。—结束示例] [§3.9.1/7]


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

如果您考虑签名类型,我相信这个答案是“不”。它等同于使用全 1 的位模式进行相等性测试,这只有在您有办法生成具有全 1 的位模式的有符号数时才有可能。对于无符号数,此表示是有保证的,但如果该数不可表示,则从无符号转换为有符号是未定义的:

如果目标类型是有符号的,则如果它可以在目标类型(和位域宽度)中表示,则该值不变;否则,该值是实现定义的。[§4.7/3]


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

我不这么认为,因为有符号幅度是允许的——0 比较等于 -0。但是对于无符号数字应该是可能的。


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

同样,我相信无符号数字的答案是“是”,而有符号数字的答案是“否”。负符号数的移位未定义:

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

于 2012-08-25T21:35:06.290 回答
9

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

该语言始终保证,如果所有形成值的位都为零,则表示的整数值也为零。

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

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

于 2012-08-25T21:42:59.257 回答
2

你已经得到了一些关于整数值表示的答案。只有一种方法可以保证为您提供内存中表示的任何对象的所有单独位:将其视为unsigned char. 这是唯一没有填充位并且保证没有陷阱表示的整数类型。因此,只要您只访问第一个字节,将类型指针转换T*为您的对象将始终有效。这样您就可以根据自己的喜好检查和设置所有字节(以及位)。unsigned char*sizeof(T)

如果您对更多细节感兴趣,这里我已经写了一些关于C中整数类型的剖析。C++ 可能与此有所不同,特别是union所描述的类型处理似乎在 C++ 中没有得到很好的定义。

于 2012-08-25T22:10:01.350 回答
1

问:如果整数类型中的任何一位为1,那么整数作为一个整体是否代表非零?(如果这是“是”,那么像符号和大小这样的一些表示将受到额外限制)

不,C 和 C++ 的标准不排除有符号幅度或反码,两者都有 +0 和 -0。虽然 +0 和 -0 必须比较相等,但它们不必具有相同的表示。

祝你现在找到一台使用有符号幅度或补码的机器。

于 2012-08-25T21:36:59.540 回答
0

如果你想让你的大脑爆炸,考虑一下:如果你将一个 int 或 long 或 long long 解释为一个 unsigned char 数组(如果你想查看所有位,这是最合理的做法),你知道未定义字节顺序,例如“bigendian”与“littleendian”。我们都(希望)知道这一点。

但更糟糕的是:int 的每个位都可以存储在char 数组的任何位中。所以有32个!如何通过真正奇怪的实现将 32 位整数的位映射到四个 8 位无符号字符的数组。幸运的是,我自己遇到的方法不止两种(而且我知道在真实计算机中还有另外一种排序方式)。

于 2015-02-19T14:44:18.357 回答
0

如果整数类型中的所有位都为零,那么整个整数是否代表零?

编辑:由于您现在已经澄清您不关心填充位,因此答案实际上是“是”。但我保留原件:

不一定,它可能是一个陷阱表示。见 C99 6.2.6.1:

对于 unsigned char 以外的无符号整数类型,对象表示的位应分为两组:值位和填充位(后者不需要任何一个)

填充位的存在允许所有 0 都是陷阱表示的可能性。(正如 Keith Thompson 在下面的评论中所指出的,最近的 C11 明确表明这种表示不是陷阱表示)。

未指定任何填充位的值

44) 填充位的某些组合可能会产生陷阱表示

如果您将问题限制为值和符号位,则答案是肯定的,因为 6.2.6.2:

如果有 N 个值位,每个位应表示 1 和 2 N -1 之间的 2 的不同幂,以便该类型的对象应能够使用纯二进制表示表示从 0 到 2 N - 1 的值;这应称为值表示。

如果符号位为零,则不应影响结果值。

如果整数类型中的任何一位为 1,那么整数作为一个整体是否表示非零?(如果这是“是”,那么像符号和大小这样的一些表示将受到额外限制)

不一定,实际上符号和大小在 6.2.6.2 中得到明确支持。

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

如果您不关心填充和符号位,则可以与 0 进行比较,但这不适用于 1 的补码表示(这是允许的),因为所有位 0 和所有位 1 都表示值 0。

否则:您可以通过 an 读取每个字节的值unsigned char *,并将结果与​​ 0 进行比较:

存储在无符号位域和无符号字符类型对象中的值应使用纯二进制表示法表示

如果你想检查一个特定的位,你可以使用 (1u << n) 构造一个合适的位掩码,但这并不一定会让你检查符号位。

是否有保证的方法来检查是否设置了任何位?

答案与上一个问题基本相同。

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

你的意思是最左边的价值位?您可以根据类型计算 INT_MAX 或 UINT_MAX 或等效项中的位,并使用它来构造一个值(通过1 << n)来 OR 原始值。

如果#1 的答案是“否”,如何遍历整数类型的位并检查每个位是 1 还是 0?

您可以使用重复左移的位掩码来执行此操作,但您只能通过这种方式检查位,而不是符号位。

于 2015-02-04T13:08:30.607 回答
-1

对于位操作,您可以创建一个具有 8 个无符号位字段的结构,并让该结构的指针指向您的字符。通过这种方式,您可以轻松访问每一位。但是编译器可能会在引擎盖下进行屏蔽,所以我认为这对程序员来说只是一种更清洁的方式。您必须检查您的编译器在执行此操作时不会更改字段的顺序。

yourstruct* pChar=(yourstruct*)(&c)
pChar.Bit7=1;
于 2012-08-25T21:14:28.453 回答
-1

让我警告这一点,我说的是一般的 C 和 C++(例如 C90 和更低版本,MS Visual C++ 等):“最大的共同点”(相对于最新/最大的 cx11“标准”)。

问:如果整数类型中的所有位都为零,那么整个整数是否代表零?

答:是的

问:如果整数类型中的任何一位为1,那么整数作为一个整体是否代表非零?(如果这是“是”,那么像符号和大小这样的一些表示将受到额外限制)

答:是的。这包括符号位,用于有符号的 int。坦率地说,我不熟悉“大小”

问:是否有保证的方法来检查是否未设置任何位?

答:始终保证“与”位掩码。

问:是否有保证的方法来检查是否设置了任何位?

答:同样,始终保证“与”位掩码。

问:设置最左边和/或最右边的位是否有保证的方法?

答:我相信您应该始终为所有实现/所有架构提供一个“MAX_INT”来确定最左边的位。

我准备被烧死……但我相信以上是准确的。我希望它有所帮助。

恕我直言...

于 2012-08-25T21:15:02.530 回答