繁体   English   中英

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

[英]Padding bits in unsigned integers and bitwise operations in C89

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

我希望让我的代码更具可移植性,并且我专注于确保我符合C89 (在这种情况下)。 我遇到的一个问题是填充整数。 拿这个极端的例子,取自GMP手册

然而,在Cray矢量系统上,可以注意到short和int总是以8个字节存储(并且sizeof指示),但仅使用32或46位。 指甲功能可以通过传递例如8*sizeof(int)-INT_BIT

我也在其他地方读过这种类型的填充。 我昨晚真的在SO上看了一篇文章(请原谅我,我没有链接,我要引用类似记忆的东西),如果你有一个带有60个可用位的双重,另外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;
}
  • 使用填充位XOR两个整数是否安全?
  • 不管填充位是什么,我不会XOR吗?

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

此外在c变量保证是0x3FFFFFFF或如果例如两个填充比特在一个都是上或b将c0xFFFFFFFF

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

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

填充位总是最高位还是最低位?


编辑12/19/2010美国东部时间下午5点 :Christoph回答了我的问题。 谢谢!
我还问过(上面)填充位是否总是最重要的位。 这在C99标准的基本原理中引用,答案是否定的。 我正在玩它安全并假设C89相同。 以下是C99基本原理对§6.2.6.2(整数类型表示)的说法:

填充位是用户可访问的无符号整数类型。 例如,假设一台机器使用一对16位短路(每个都有自己的符号位)来构成一个32位的int,而在这个32位的int中使用时,忽略了short short的符号位。 然后,作为32位有符号整数,在确定32位有符号int的值时会忽略一个填充位(在32位的中间)。 但是,如果将此32位项目视为32位无符号整数,则该填充位对用户程序可见。 C委员会被告知有一台机器以这种方式工作,这就是填充位被添加到C99的一个原因。

脚注44和45提到奇偶校验位可能是填充位。 委员会不知道任何具有用户可访问的奇偶校验位的机器在整数内。 因此,委员会不知道任何将奇偶校验位视为填充位的机器。


编辑12/28/2010美国东部时间下午3点 :几个月前我在comp.lang.c上发现了一个有趣的讨论。

Dietmar提出的一点我感兴趣:

让我们注意,填充位不是存在陷阱表示所必需的; 不表示对象类型值的值位组合也可以。

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

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

编辑:

C90根本没有提到整数填充,但据我所知,“隐形”前置或尾随整数填充位不应违反标准(我没有通过所有相关部分来确保这是真的情况虽然); probaby是C99基本原理中提到的混合填充和值位的问题,因为否则,标准就不需要改变了。

至于用户可访问的含义:填充位是可访问的,只要你可以通过在((unsigned char *)&foo)[…]上使用位操作来获取foo (包括填充)的任何位。 但是在修改填充位时要小心:结果不会改变整数的值,但可能会创建陷阱表示。 在C90的情况下,这是隐式未指定的(如未提及的那样),在C99的情况下,它是实现定义的。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM