gpt4 book ai didi

c - 无符号整数中的填充位和 C89 中的按位运算

转载 作者:太空狗 更新时间:2023-10-29 16:31:13 27 4
gpt4 key购买 nike

我有很多代码对无符号整数执行按位运算。我编写代码时假设这些操作是在没有任何填充位的固定宽度整数上进行的。例如,一个 32 位无符号整数数组,其中所有 32 位都可用于每个整数。

我希望让我的代码更具可移植性,我专注于确保我是 C89 compliant (在这种情况下)。我遇到的问题之一是可能的填充整数。举这个极端的例子,取自 GMP manual :

However on Cray vector systems it may be noted that short and int are always stored in 8 bytes (and with sizeof indicating that) but use only 32 or 46 bits. The nails feature can account for this, by passing for instance 8*sizeof(int)-INT_BIT.

我也在其他地方读到过这种类型的填充。我昨晚实际上读到了一篇关于 SO 的帖子(请原谅我,我没有链接,我会从内存中引用类似的东西)如果你有,比如说,一个有 60 个可用位的 double,其他 4 个可以用于填充,这些填充位可以用于某些内部目的,因此不能修改它们。


例如,假设我的代码是在一个平台上编译的,其中 unsigned int 类型的大小为 4 个字节,每个字节为 8 位,但是最重要的 2 位是填充位。 UINT_MAX 在那种情况下会是 0x3FFFFFFF (1073741823) 吗?

#include <stdio.h>
#include <stdlib.h>

/* padding bits represented by underscores */
int main( int argc, char **argv )
{
unsigned int a = 0x2AAAAAAA; /* __101010101010101010101010101010 */
unsigned int b = 0x15555555; /* __010101010101010101010101010101 */
unsigned int c = a ^ b; /* ?? __111111111111111111111111111111 */
unsigned int d = c << 5; /* ?? __111111111111111111111111100000 */
unsigned int e = d >> 5; /* ?? __000001111111111111111111111111 */

printf( "a: %X\nb: %X\nc: %X\nd: %X\ne: %X\n", a, b, c, d, e );
return 0;
}
  • 用填充位对两个整数进行异或是否安全?
  • 无论填充位是什么,我都不会异或吗?

我找不到 C89 中涵盖的这种行为。

此外,c 变量保证为 0x3FFFFFFF 或者如果两个填充位都在 a 或 b 中,则 c0xFFFFFFFF

de 相同的问题。我是通过移位来操纵填充位吗?我希望在下面看到这个,假设 32 位和用于填充的 2 个最高有效位,但我想知道是否可以保证这样的事情:

a: 2AAAAAAA
b: 15555555
c: 3FFFFFFF
d: 3FFFFFE0
e: 01FFFFFF

此外,填充位总是最高有效位还是最低有效位?


EDIT 12/19/2010 5PM EST:Christoph 回答了我的问题。谢谢!
我还问过(上文)填充位是否总是最重要的位。 C99 标准的基本原理中引用了这一点,答案是否定的。我正在谨慎行事,并假设 C89 也是如此。以下是 C99 基本原理对 §6.2.6.2(整数类型的表示)的具体说明:

Padding bits are user-accessible in an unsigned integer type. For example, suppose a machine uses a pair of 16-bit shorts (each with its own sign bit) to make up a 32-bit int and the sign bit of the lower short is ignored when used in this 32-bit int. Then, as a 32-bit signed int, there is a padding bit (in the middle of the 32 bits) that is ignored in determining the value of the 32-bit signed int. But, if this 32-bit item is treated as a 32-bit unsigned int, then that padding bit is visible to the user’s program. The C committee was told that there is a machine that works this way, and that is one reason that padding bits were added to C99.

Footnotes 44 and 45 mention that parity bits might be padding bits. The committee does not know of any machines with user-accessible parity bits within an integer. Therefore, the committee is not aware of any machines that treat parity bits as padding bits.


EDIT 12/28/2010 3PM EST:几个月前我在 comp.lang.c 上发现了一个有趣的讨论。

Dietmar 提出的一个观点我觉得很有趣:

Let's note that padding bits are not necessary for the existence of trap representations; combinations of value bits which do not represent a value of the object type would also do.

最佳答案

按位运算(如算术运算)对值进行运算并忽略填充。实现可能会也可能不会修改填充位(或在内部使用它们,例如作为奇偶校验位),但可移植的 C 代码永远无法检测到这一点。任何值(包括 UINT_MAX)都不会包含填充。

如果您使用 sizeof (int) * CHAR_BIT 之类的东西然后尝试使用移位来访问所有这些位,则整数填充可能会导致问题。如果你想便携,要么只使用 (unsigned) char,固定大小的整数(C99 添加),要么以编程方式确定值位数。这可以在编译时使用预处理器通过将 UINT_MAX 与 2 的幂进行比较或在运行时使用位操作来完成。

编辑:

C90 根本没有提到整数填充,但据我所知,“不可见的”前面或后面的整数填充位不应该违反标准(我没有通过所有相关部分来确保这是不过,确实如此);正如 C99 基本原理中提到的那样,可能存在混合填充和值位的问题,否则就不需要更改标准。

至于用户可访问的含义:填充位是可访问的,因为您总是可以通过对 ((unsigned)字符 *)&foo)[…]。但是,修改填充位时要小心:结果不会更改整数的值,但可能会创建一个陷阱表示。在 C90 的情况下,这是隐式未指定的(因为根本没有提到),在 C99 的情况下,它是实现定义的。

但这不是基本原理引用的内容:引用的体系结构通过两个 16 位整数表示 32 位整数。对于无符号类型,生成的整数具有 32 个值位和 32 位精度;在有符号整数的情况下,它只有 31 个值位和 30 精度:16 位整数的符号位之一用作 32 位整数的符号位,另一个被忽略,从而创建由值位包围的填充位。现在,如果您将 32 位有符号整数作为无符号整数访问(这是明确允许的并且不违反 C99 别名规则),则填充位变为(用户可访问的)值位。

关于c - 无符号整数中的填充位和 C89 中的按位运算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4475540/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com