簡體   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