簡體   English   中英

用1向右移動數組

[英]Shift an array to the right with 1

我正在嘗試使用一些二進制1將無符號char數組移到右側。

例如:0000 0000 | 我換8次的0000 1111將給我0000 1111 | 1111 1111(二進制左移)

因此,在我的數組中,我將得到:{0x0F,0x00,0x00,0x00} => {0xFF,0x0F,0x00,0x00}(數組中的右移)

我目前使用函數memmove擁有此功能:

unsigned char * dataBuffer = {0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

unsigned int shift = 4;
unsigned length = 8;

memmove(dataBuffer, dataBuffer - shift, length + shift);    
for(int i = 0 ; i < 8 ; i++) printf("0x%X ", dataBuffer[i]);

Output: 0x0 0x0 0x0 0x0 0xF 0x0 0x0 0x0
Expected output: 0xFF 0x0 0x0 0x0 0x0 0x0 0x0 0x0

如您所見,我設法逐個元素移動了僅數組元素,但我不知道如何用1替換0。我猜想使用memset可以工作,但我不能正確使用它。

謝謝你的幫助!

編輯:這是為了填充exFAT磁盤的位圖區域。 在磁盤中寫入群集時,必須將位圖的相應位設置為1(第一個群集是第一位,第二個群集是第二位,...)。

新格式化的驅動器在位圖的第一個字節中將包含0x0F,因此如果編寫8個簇,建議的示例與我的需求相對應,我需要將值移位8次並用1填充。

在代碼中,我編寫了4個簇,需要將值移位4位,但是將其移位4個字節。

將問題設置為已解決,就無法做我想要的事情。 除了需要移位數組的位,還需要分別移位數組的每個字節。

將問題設置為已解決,就無法做我想要的事情。 無需移動數組的位,而是需要分別編輯數組的每個位。

這是可以幫助其他人的代碼:

unsigned char dataBuffer[11] = {0x0F, 0x00, 0x00, 0x00, 0, 0, 0, 0};
unsigned int sizeCluster = 6;
unsigned int firstCluster = 4;
unsigned int bitIndex = firstCluster % 8;
unsigned int byteIndex = firstCluster / 8;
for(int i = 0 ; i < sizeCluster; i++){
    dataBuffer[byteIndex] |= 1 << bitIndex;
    //printf("%d ", bitIndex);
    //printf("%d \n\r", byteIndex);
    bitIndex++;
    if(bitIndex % 8 == 0){
        bitIndex = 0;
        byteIndex++;
    }
}
for(int i = 0 ; i < 10 ; i++) printf("0x%X ", dataBuffer[i]);

OUTPUT: 0xFF 0x3 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 

sizeCluster是我要在位圖中添加的簇數firstCluster是我可以寫入數據的第一個簇(使用了4個簇:0、1、2和3,所以我從4開始)。 bitIndex用於修改數組字節中的右位=>每次遞增。 byteIndex用於修改數組的右字節=>每當該位等於7時就遞增。

如果出於性能原因不想使用C ++ std :: bitset,則可以按如下方式重寫代碼:

#include <cstdio>
#include <cstdint>

    // buffer definition
    constexpr size_t clustersTotal = 83;
    constexpr size_t clustersTotalBytes = (clustersTotal+7)>>3; //ceiling(n/8)
    uint8_t clustersSet[clustersTotalBytes] = {0x07, 0};
        // clusters 0,1 and 2 are already set (for show of)

    // helper constanst bit masks for faster bit setting
    // could be extended to uint64_t and array of qwords on 64b architectures
    // but I couldn't be bothered to write all masks by hand.
    // also I wonder when the these lookup tables would be large enough
    // to disturb cache locality, so shifting in code would be faster.
    const uint8_t bitmaskStarting[8] = {0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80};
    const uint8_t bitmaskEnding[8] = {0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
    constexpr uint8_t bitmaskFull = 0xFF;

    // Input values
    size_t firstCluster = 6;
    size_t sizeCluster = 16;

    // set bits (like "void setBits(size_t firstIndex, size_t count);" )
    auto lastCluster = firstCluster + sizeCluster - 1;
    printf("From cluster %d, size %d => last cluster is %d\n",
           firstCluster, sizeCluster, lastCluster);
    if (0 == sizeCluster || clustersTotal <= lastCluster)
        return 1;     // Invalid input values
    auto firstClusterByte = firstCluster>>3; // div 8
    auto firstClusterBit = firstCluster&7;   // remainder
    auto lastClusterByte = lastCluster>>3;
    auto lastClusterBit = lastCluster&7;
    if (firstClusterByte < lastClusterByte) {
        // Set the first byte of sequence (by mask from lookup table (LUT))
        clustersSet[firstClusterByte] |= bitmaskStarting[firstClusterBit];
        // Set bytes between first and last (simple 0xFF - all bits set)
        while (++firstClusterByte < lastClusterByte)
            clustersSet[firstClusterByte] = bitmaskFull;
        // Set the last byte of sequence (by mask from ending LUT)
        clustersSet[lastClusterByte] |= bitmaskEnding[lastClusterBit];
    } else {    //firstClusterByte == lastClusterByte special case
        // Intersection of starting/ending LUT masks is set
        clustersSet[firstClusterByte] |=
            bitmaskStarting[firstClusterBit] & bitmaskEnding[lastClusterBit];
    }

    for(auto i = 0 ; i < clustersTotalBytes; ++i)
        printf("0x%X ", clustersSet[i]); // Your debug display of buffer

不幸的是,我沒有介紹任何版本(您與我的版本),所以我不知道在兩種情況下優化的C編譯器輸出的質量如何。 在la腳的C編譯器和386-586處理器時代,我的版本會更快。 使用現代C編譯器,LUT的使用可能會適得其反,但是除非有人通過某些分析結果證明我錯了,否則我仍然認為我的版本會更高效。

就是說,由於在此之前可能涉及寫入文件系統,因此即使使用您的變量,設置位也可能需要大約CPU時間的0.1%,I / O等待將是主要因素。

因此,我將其發布為一個示例,說明如何以不同的方式完成操作。

編輯:

另外,如果您相信clib優化,則:

        // Set bytes between first and last (simple 0xFF - all bits set)
        while (++firstClusterByte < lastClusterByte)
            clustersSet[firstClusterByte] = bitmaskFull;

可以重用clib memset魔術:

//#include <cstring>
    // Set bytes between first and last (simple 0xFF - all bits set)
    if (++firstClusterByte < lastClusterByte)
        memset(clustersSet, bitmaskFull, (lastClusterByte - firstClusterByte));

暫無
暫無

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

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