簡體   English   中英

C / C ++位數組或位向量

[英]C/C++ Bit Array or Bit Vector

我正在學習C / C ++編程,遇到了“位數組”或“位向量”的用法。 無法理解其目的? 這是我的疑問-

  1. 它們用作布爾標志嗎?
  2. 可以使用int數組嗎? (當然,更多的內存,但是..)
  3. 掩膜的概念是什么?
  4. 如果位屏蔽是獲得相應標志的簡單位操作,那么如何為它們編寫一個程序? 頭上執行此操作以了解與十進制數字相對應的標志是不是很困難?

我正在尋找應用程序,以便可以更好地理解。 例如

問:您將得到一個文件,其中包含整數(1到1百萬)。 有一些重復項,因此缺少一些數字。 找到找到遺漏號碼的最快方法?

對於上述問題,我已經閱讀了告訴我使用位數組的解決方案。 一個整數如何存儲一個整數?

我認為您在數組和數字之間感到困惑,尤其是操縱二進制數字的含義。

我將通過示例進行介紹。 假設您有許多錯誤消息,並且想要從函數的返回值中返回它們。 現在,您可以將錯誤1,2,3,4 ...標記為您的腦海,但是,僅給出一個數字,您如何確定發生了哪些錯誤?

現在,嘗試標記錯誤1,2,4,8,16 ...基本上增加2的冪。 為什么這樣做? 好吧,當您以2為基數時,您正在操縱一個像00000000數字,其中每個數字對應於2的冪乘以其從右邊開始的位置。 因此,假設發生錯誤1、4和8。 好吧,那可以表示為00001101 相反,第一個數字= 1 * 2 ^ 0,第三個數字1 * 2 ^ 2和第四個數字1 * 2 ^ 3。 將它們全部加在一起就可以得到13。

現在,我們可以通過應用位掩碼來測試是否發生了此類錯誤。 例如,如果您想找出是否發生錯誤8 ,請使用8 = 00001000的位表示形式。 現在,為了提取是否已發生該錯誤,請使用二進制文件,如下所示:

  00001101
& 00001000
= 00001000

我確定您知道an和and的工作原理或可以從上面推論得出-在數字上工作,如果任何兩位數字均為1,則結果為1,否則為0。

現在,在C中:

int func(...)
{
    int retval = 0;

    if ( sometestthatmeans an error )
    {
        retval += 1;
    }


    if ( sometestthatmeans an error )
    {
        retval += 2;
    }
    return retval
}

int anotherfunc(...)
{
    uint8_t x = func(...)

    /* binary and with 8 and shift 3 plaes to the right
     * so that the resultant expression is either 1 or 0 */
    if ( ( ( x & 0x08 ) >> 3 ) == 1 )
    {
        /* that error occurred */
    }
}

現在,要實用。 當內存稀疏並且協議沒有冗長的xml等的奢侈時,通常將字段定義為這么多位寬。 在該字段中,將各種位(標志,2的冪)分配給某種含義,並應用二進制運算來推斷是否已設置它們,然后對其進行運算。

我還應該補充一點,二進制運算在思想上與計算機的底層電子設備非常接近。 想象一下,如果位字段對應於各種電路的輸出(是否帶電)。 通過使用足夠多的上述電路組合,您可以制造出……台計算機。

關於bits數組的用法:

如果您知道“只有”一百萬個數字,則使用一百萬個比特的數組。 在開始時,所有位都將為零,並且每次您讀取一個數字時-將此數字用作索引並將該索引中的位更改為1(如果還不是一個的話)。

讀取所有數字后-缺失的數字是數組中零的索引。

例如,如果我們只有0-4之間的數字,則數組開頭應為:0 0 0 00。如果我們讀取數字:3、2、2,則數組將如下所示:read 3- > 0 0 0 1 0.再次讀取3-> 0 0 0 1 0.讀取2-> 0 0 1 1 0.檢查零的索引:0,1,4-這些是缺少的數字

順便說一句,您當然可以使用整數而不是位,但是它可能占用(取決於系統)32倍的內存

西萬

位向量的位陣列用作從位置到某個位值的映射。 是的,它基本上與Bool數組相同,但是典型的Bool實現長度為一到四個字節,並且占用了太多空間。

通過使用單詞數組和二進制掩碼操作以及轉移來存儲和檢索它們,我們可以更有效地存儲相同數量的數據(減少了使用的總內存,減少了對內存的訪問,減少了緩存未命中,減少了內存頁面交換)。 訪問單個位的代碼仍然非常簡單。

還有一些用C語言內置的位域支持(您編寫int i:1;類的東西int i:1;說“只消耗一位”),但是它不適用於數組,並且您對整體結果的控制較少(詳細信息實施方式取決於編譯器和對齊問題)。

以下是回答“搜索遺漏號碼”問題的一種可能方法。 我將int大小固定為32位以使事情簡單,但是可以使用sizeof(int)編寫它以使其可移植。 並且(取決於編譯器和目標處理器)只能使用>> 5代替/ 32& 31& 31代替% 32來使代碼更快,但這只是為了給出想法。

#include <stdio.h>
#include <errno.h>
#include <stdint.h>

int main(){
    /* put all numbers from 1 to 1000000 in a file, except 765 and 777777 */
    {
        printf("writing test file\n");
        int x = 0;
        FILE * f = fopen("testfile.txt", "w");
        for (x=0; x < 1000000; ++x){
            if (x == 765 || x == 777760 || x == 777791){
                continue;
            }
            fprintf(f, "%d\n", x);
        }
        fprintf(f, "%d\n", 57768); /* this one is a duplicate */
        fclose(f);
    }

    uint32_t bitarray[1000000 / 32];

    /* read file containing integers in the range [1,1000000] */
    /* any non number is considered as separator */
    /* the goal is to find missing numbers */
    printf("Reading test file\n");
    {
        unsigned int x = 0;
        FILE * f = fopen("testfile.txt", "r");
        while (1 == fscanf(f, " %u",&x)){
            bitarray[x / 32] |= 1 << (x % 32);
        }
        fclose(f);
    }
    /* find missing number in bitarray */
    {
        int x = 0;
        for (x=0; x < (1000000 / 32) ; ++x){
            int n = bitarray[x];
            if (n != (uint32_t)-1){
                printf("Missing number(s) between %d and %d [%x]\n",
                    x * 32, (x+1) * 32, bitarray[x]);
                int b;
                for (b = 0 ; b < 32 ; ++b){
                    if (0 == (n & (1 << b))){
                        printf("missing number is %d\n", x*32+b);
                    }
                }
            }
        }
    }
}

位數組或位向量可以是布爾值數組 通常,布爾變量至少需要存儲一個字節,但是在位數組/向量中僅需要一位。 如果您有很多這樣的數據,這將很方便,這樣可以節省大量內存。

另一種用法是,如果您的數字不完全適合 8、16、32或64位大小的標准變量 您可以通過這種方式將一個由4位組成的數字存儲到16位的位向量中,一個是2位,另一個是10位。 通常,您必須使用3個大小分別為8,8和16位的變量,因此浪費的存儲空間僅為50%。

但是所有這些用途很少在業務應用中使用,當通過pinvoke / interop功能連接驅動程序並執行低級編程時,經常會使用這些用途。

它用於位標志存儲,以及用於解析不同的二進制協議字段,其中1個字節被划分為多個位字段。 它廣泛用於TCP / IP等協議,高達ASN.​​1編碼,OpenPGP數據包等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM