Ç问题:在无符号整数和位操作填充比特(C89) [英] C question: Padding bits in unsigned integers and bitwise operations (C89)

查看:233
本文介绍了Ç问题:在无符号整数和位操作填充比特(C89)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有很多code,关于无符号整数执行位操作。我写我的code的假设,这些行动是在没有任何填充位固定宽度的整数。对于其中的32位无符号整数数组可为每个整数所有32位示例。

我期待让我的code更便携,我专注于确保我的 C89兼容(在这种情况下)。其中一个是我遇到的一个问题是可能的填充整数。采取这种极端的例子,从 GMP手动采取:


  

上。然而克雷载体系统它可以指出,短和INT总是存储在8个字节(并用的sizeof指示),但仅使用32或46位。指甲功能可以解决这个问题,通过传递例如8 * sizeof的(INT)-INT_BIT。


我也看到了有关在其他地方这种类型的填充。其实我对SO昨晚(原谅我,我没有链接,我要举从内存中类似的东西)的地方,如果你有,比如说,60位可用其他4个可能的双重阅读职位可用于填充和那些填充位可以成为内部的一些目的,所以他们不能被修改。结果
结果
结果
因此,让我们说,例如我的code编译,其中一个unsigned int类型是在4个字节大小的平台上,每个字节为8位,但最显著2位是填充位。在这种情况下将UINT_MAX是0x3FFFFFFF(1073741823)?

 的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;/ *填充比特重新用下划线psented $ P $ * /
INT主(INT ARGC,字符** 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 \\注意:%X \\ NC:%X \\ ND:%X \\ NE:%X \\ n,A,B,C,D,E);
    返回0;
}

是安全的异或两个整数与填充位?结果
我岂不XOR任何填充比特是谁?结果
我找不到这种行为涉及的C89。结果
另外是C变种保证是0x3FFFFFFF或者如果例如两个填充比特在a或b都是关于将c是0xFFFFFFFF的?结果
与D和E相同的问题。我是通过改变操作填充比特?
我希望下面看到这一点,假设与用于填充的2最显著位32位,但我想知道,如果这样的事情是有保障:

  A:2AAAAAAA
乙:15555555
C:3FFFFFFF
D:3FFFFFE0
E:01FFFFFF

另外是填充比特总是最显著位或它们可以是至少显著位?

谢谢你们

结果

修改12/19/2010 17 EST :克里斯托夫已经回答了我的问题。谢谢!结果
我也(上图)填充位是否总是最显著比特问道。这是在对C99标准的基本原理引,答案是否定的。我玩它的安全和承担C89相同。下面是具体是什么理由C99为说§6.2.6.2(再$整数类型的对$ psentation):


  

填充位是用户可访问的在一个无符号整数类型。例如,假设一台机器使用一对16位短裤(每个都有自己的符号位)来弥补一个32位int和下短的符号位在这32位int使用时被忽略。然后,作为一个32位有符号整数,存在在确定的32位有符号整数的值忽略的填充位(在32位的中间)。但是,如果该32位项目作为一个32位无符号整型处理,然后该填充位是给用户的程序可见。的C委员会被告知有这种方式工作的一台机器,那就是填充比特添加到C99的原因之一。


  
  

脚注44和45提,奇偶比特可能是填充比特。委员会不知道跟一个整数范围内用户可访问的奇偶校验位的机器。因此,委员会不知道治疗奇偶校验位作为填充位的机器。


结果

修改12/28/2010美国东部时间下午3点:我发现从几个月前就comp.lang.c一个有趣的讨论结果。
<一href=\"http://www.velocityreviews.com/forums/t732675-bitwise-operator-effects-on-padding-bits.html\">Bitwise在填充位操作效果(VelocityReviews阅读器)结果
<一href=\"http://groups.google.com/group/comp.lang.c/browse_thread/thread/aa6f839c5a046ac1?fwc=2\">Bitwise在填充位操作效果(谷歌组备用链路)结果
迪特马尔我发现有趣提出一个观点:


  

让的注意,填充比特是不需要阱再presentations的存在;不重新present对象类型的值值的位的组合也将这样做。



解决方案

位运算(如算术运算)的值进行操作,而忽略填充。实施可以或可以不修改填充比特(或在内部使用它们,例如作为奇偶比特),但移植的C code将永远无法检测到这一点。任何值(包括 UINT_MAX )将不包括填充。

在哪里是如果你使用之类的东西的sizeof(int)的整数填充可能导致问题* CHAR_BIT ,然后尝试用转移到访问所有这些位。如果你想成为便携,要么只使用(无符号字符,固定大小的整数(C99的加法)或确定值的位数编程。这可以在编译时用preprocessor通过比较 UINT_MAX 通过使用位运算来完成对2或在运行时的力量。

编辑:

C90并没有提及整数填充所有,但据我所知,'看不见的'preceding或尾随整数填充位应不违反标准(我没有去通过所有相关的部分,使肯定这真的是这样,虽然);有probaby与作为C99的理由,否则,也不会需要标准被改变提到的混合填充和值位的问题。

至于用户可访问的意义:填充位都可以访问,只要你能alwaye得到在任何位(包括填充)通过使用位运算((无符号字符*)及富)[...] 。修改填充比特时,虽然要小心:结果不会改变整数值,但可以创建是一个陷阱,再presentation不过。在C90的情况下,这是隐含指定(如在所有未提及),在C99中的情况下,这是实现定义的。

这是不是有什么理由报价在,虽然:通过两​​个16位整数引用架构重新presents 32位整数。在无符号类型的情况下,所得到的整数具有32个值的位和32个一precision;在符号整数的情况下,只有31个值的位和30个一precision:16位整数的符号位中的一个被用作32位整数的符号位,另一个被忽略,从而创造价值所包围位的填充位。现在,如果你访问一个32位有符号整数无符号整数(这是明确允许和不违反C99别名规则),填充位成为(用户访问)值位。

I have a lot of code that performs bitwise operations on unsigned integers. I wrote my code with the assumption that those operations were on integers of fixed width without any padding bits. For example an array of 32 bit unsigned integers of which all 32 bits available for each integer.

I'm looking to make my code more portable and I'm focused on making sure I'm C89 compliant (in this case). One of the issues that I've come across is possible padded integers. Take this extreme example, taken from the 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.

I've also read about this type of padding in other places. I actually read of a post on SO last night (forgive me, I don't have the link and I'm going to cite something similar from memory) where if you have, say, a double with 60 usable bits the other 4 could be used for padding and those padding bits could serve some internal purpose so they cannot be modified.


So let's say for example my code is compiled on a platform where an unsigned int type is sized at 4 bytes, each byte being 8 bits, however the most significant 2 bits are padding bits. Would UINT_MAX in that case be 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;
}

is it safe to XOR two integers with padding bits?
wouldn't I XOR whatever the padding bits are?
I can't find this behavior covered in C89.
furthermore is the c var guaranteed to be 0x3FFFFFFF or if for example the two padding bits were both on in a or b would c be 0xFFFFFFFF ?
same question with d and e. am i manipulating the padding bits by shifting? I would expect to see this below, assuming 32 bits with the 2 most significant bits used for padding, but I want to know if something like this is guaranteed:

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

Also are padding bits always the most significant bits or could they be the least significant bits?

Thanks guys


EDIT 12/19/2010 5PM EST: Christoph has answered my question. Thanks!
I had also asked (above) whether padding bits are always the most significant bits. This is cited in the rationale for the C99 standard, and the answer is no. I am playing it safe and assuming the same for C89. Here is specifically what the C99 rationale says for §6.2.6.2 (Representation of Integer Types):

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: I found an interesting discussion on comp.lang.c from a few months ago.
Bitwise Operator Effects on Padding Bits (VelocityReviews reader)
Bitwise Operator Effects on Padding Bits (Google Groups alternate link)
One point made by Dietmar which I found interesting:

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.

解决方案

Bitwise operations (like arithmetic operations) operate on values and ignore padding. The implementation may or may not modify padding bits (or use them internally, eg as parity bits), but portable C code will never be able to detect this. Any value (including UINT_MAX) will not include the padding.

Where integer padding might lead to problems on is if you use things like sizeof (int) * CHAR_BIT and then try to use shifts to access all these bits. If you want to be portable, either only use (unsigned) char, fixed-sized integers (a C99 addition) or determine the number of value-bits programatically. This can be done at compile-time with the preprocessor by comparing UINT_MAX against powers of 2 or at runtime by using bit-operations.

edit:

C90 does not mention integer padding at all, but as far as I can tell, 'invisible' preceding or trailing integer padding bits shouldn't violate the standard (I didn't go through all relevant sections to make sure this is really the case, though); there probaby are problems with mixed padding and value bits as mentioned in the C99 rationale because otherwise, the standard would not have needed to be changed.

As to the meaning of user-accessible: Padding bits are accessible insofar as you can alwaye get at any bit of foo (including padding) by using bit-operations on ((unsigned char *)&foo)[…]. Be careful when modifying the padding bits, though: the result won't change the value of the integer, but might create be a trap-representation nevertheless. In case of C90, this is implicitly unspecified (as in not mentioned at all), in case of C99, it's implementation-defined.

This was not what the rationale quotation was about, though: the cited architecture represents 32-bit integers via two 16-bit integers. In case of unsigned types, the resulting integer has 32 value bits and a precision of 32; in case of signed integers, it only has 31 value bits and a precision of 30: one of the sign bits of the 16-bit integers is used as the sign bit of the 32-bit integer, the other one is ignored, thus creating a padding bit surrounded by value bits. Now, if you access a 32-bit signed integer as an unsigned integer (which is explicitly allowed and does not violate the C99 aliasing rules), the padding bit becomes a (user-accessible) value bit.

这篇关于Ç问题:在无符号整数和位操作填充比特(C89)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆