Ano*_*Guy 17 c bit-manipulation padding bitwise-operators
我有很多代码对无符号整数执行按位运算.我编写了我的代码,假设这些操作是在固定宽度的整数上,没有任何填充位.例如,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;
}
Run Code Online (Sandbox Code Playgroud)
使用填充位XOR两个整数是否安全?
不管填充位是什么我不会XOR?
我找不到C89中涵盖的这种行为.
此外,c var保证为0x3FFFFFFF,或者例如,如果两个填充位在a或b中都打开,则c将为0xFFFFFFFF?
与d和e相同的问题.我通过移动来操纵填充位吗?我希望在下面看到这一点,假设32位用于填充的2个最高有效位,但我想知道这样的事情是否有保证:
a: 2AAAAAAA
b: 15555555
c: 3FFFFFFF
d: 3FFFFFE0
e: 01FFFFFF
Run Code Online (Sandbox Code Playgroud)
填充位总是最高位还是最低位?
多谢你们
编辑12/19/2010美国东部时间下午5点:Christoph回答了我的问题.谢谢!
我还问过(上面)填充位是否总是最重要的位.这在C99标准的基本原理中引用,答案是否定的.我正在玩它安全并假设C89相同.以下是C99基本原理对§6.2.6.2(整数类型表示)的说法:
填充位是用户可访问的无符号整数类型.例如,假设一台机器使用一对16位短路(每个都有自己的符号位)来构成一个32位的int,并且当在这个32位int中使用时,忽略较低short的符号位.然后,作为32位有符号整数,在确定32位有符号int的值时会忽略一个填充位(在32位的中间).但是,如果将此32位项目视为32位无符号整数,则该填充位对用户程序可见.C委员会被告知有一台机器以这种方式工作,这就是填充位被添加到C99的一个原因.
脚注44和45提到奇偶校验位可能是填充位.委员会不知道任何具有用户可访问的奇偶校验位的机器在整数内.因此,委员会不知道任何将奇偶校验位视为填充位的机器.
编辑12/28/2010美国东部时间下午3点:几个月前我在comp.lang.c上发现了一个有趣的讨论.
填充位上的按位运算符效果(VelocityReviews阅读器)
填充位上的按位运算符效果(Google Groups备用链接)
Dietmar提出的一点我感兴趣:
让我们注意,填充位不是存在陷阱表示所必需的; 不表示对象类型值的值位组合也可以.
Chr*_*oph 10
按位运算(如算术运算)对值进行操作并忽略填充.实现可能会也可能不会修改填充位(或在内部使用它们,例如作为奇偶校验位),但便携式C代码将永远无法检测到这一点.任何值(包括UINT_MAX)都不包括填充.
如果使用类似的东西,整数填充可能导致问题sizeof (int) * CHAR_BIT,然后尝试使用shift来访问所有这些位.如果你想要是可移植的,要么只使用(unsigned)char,固定大小的整数(添加C99),要么以编程方式确定值位数.这可以在编译时通过预处理器通过比较UINT_MAX2的幂或在运行时通过使用位操作来完成.
编辑:
C90根本没有提到整数填充,但据我所知,'隐形'前置或尾随整数填充位不应违反标准(我没有通过所有相关部分来确保确实如此)虽然); probaby是C99基本原理中提到的混合填充和值位的问题,因为否则,标准就不需要改变了.
至于用户可访问的含义:填充位是可访问的,只要你可以foo通过使用位操作来获取任何位(包括填充)((unsigned char *)&foo)[…].但是在修改填充位时要小心:结果不会改变整数的值,但可能会创建陷阱表示.在C90的情况下,这是隐式未指定的(如未提及的那样),在C99的情况下,它是实现定义的.
然而,这不是基本原理引用的内容:引用的体系结构通过两个16位整数表示32位整数.在无符号类型的情况下,结果整数具有32个值位并且精度为32; 在有符号整数的情况下,它只有31个值位且精度为30:16位整数的符号位之一用作32位整数的符号位,另一个被忽略,从而创建由值位包围的填充位.现在,如果您将32位有符号整数作为无符号整数(明确允许并且不违反C99别名规则)访问,则填充位将成为(用户可访问的)值位.