2016-06-16 72 views
0

符号なしの文字の配列をバイナリで右にシフトしようとしています。配列を右にシフトする1

例:0000 0000 |私が8回シフトする0000 1111は私に0000 1111 | 1111 1111(バイナリの左シフト)

だから私のアレイにIが得る:{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は動作するかもしれませんが、正しく使用することはできません。

ありがとうございました!

EDIT:exFATディスクのビットマップゾーンを埋めるためです。ディスクにクラスタを書き込むときは、ビットマップの対応するビットを1(最初のクラスタは最初のビット、2番目のクラスタは2番目のビット、...)に設定する必要があります。

提案の例では、私は8つのクラスタを書いた場合、私は値を8回シフトし、1

でそれを埋めるために必要があります私のニーズに対応して、新たにフォーマットされたドライブは、ビットマップの最初のバイトに0x0Fに含まれます

コードでは、4クラスタを書き込んで4ビットシフトする必要がありますが、4バイトシフトします。

解決策として質問を設定すると、私がしたいことはできません。配列のビットをシフトする代わりに、配列の各バイトを別々にシフトする必要があります。

+2

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

はCLIB memset魔法を再利用することができます問題を述べる。彼らはどのように見えるのですか?入力と出力?期待される行動は正確には何ですか?あなたは一例を挙げましたが、あなたの要件を本当にカバーしていますか?何のためにそれが必要ですか? – Elyasin

+0

exFATディスクのビットマップゾーンを埋めるためです。ディスクにクラスタを書き込むときは、ビットマップの対応するビットを1(最初のクラスタは最初のビット、2番目のクラスタは2番目のビット、...)に設定する必要があります。 ビットマップの最初のバイトに0x0Fが新しくフォーマットされたドライブに格納されるので、8つのクラスタを書き込む場合、提案した例が私のニーズに対応します。値を8回シフトして1にする必要があります。 –

+1

シフトはしません 'ここでは意味をなさない - まず、書き込みを行っているクラスターを選択しているが、シフトを伴わないクラスターは、書き込み中のクラスターに対応するビットを設定するだけである(それらは連続していない可能性がある)。 2番目の例では、右にシフトしていることを示していますが、通常のビットシフトの反対である0ではなく1でパディングしています。ビットシフトするには、<< and >>ビットレベルの演算子を使用して行います。シフトする際に使用する任意のワードサイズでオーバフローを管理します。しかし、あなたの説明に基づいて、それはあなたが本当に望むようには聞こえません。 –

答えて

0

解決策として質問を設定すると、私がしたいことはできません。配列のビットをシフトする代わりに、配列の各ビットを別々に編集する必要があります。それは他の誰かを助けることができればここで

はコードです:

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に等しくなるたびに増加します。

+1

あなたは配列をシフトしていません、あなたは特定のクラスタの特定のビットを設定しています、これは古典的なビットマスクセットです。質問は、なぜあなたはC++ [ビットセット](http://www.cplusplus.com/reference/bitset/bitset/)を使わないのですか? – Ped7g

+0

ほとんどの場合(たぶん実際に)、私は配列をバイトとして操作します。ビット。これは私の考え方のビットマップにのみ必要なので、ビット単位で変換することは一度も考えていません(私は今までFAT32を使用していました)。 bitset関数が分からない場合は、最適化すると思いますか?データの読み書きに使用するsata関数はunsigned charバッファを使用するため、バイトに変換する必要があります。 –

0

パフォーマンス上の理由から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コンパイラ出力の品質が何であるか見当がつかない。ラメCコンパイラと386-586プロセッサの時代、私のバージョンははるかに高速でした。現代のCコンパイラでは、LUTの使用は少し生産的ではないかもしれませんが、誰かが何らかのプロファイリング結果によって私を間違っていない限り、私はまだ私のバージョンがはるかに効率的だと思います。

言い換えれば、ファイルシステムへの書き込みがこれに先行している可能性が高いため、設定ビットはおそらく変種であってもCPU時間の約0.1%を要し、I/O待機が大きな要因になります。

私はこれを例のように投稿しています。どのように物事を別の方法で行うことができますか?

編集:あなたはCLIBの最適化を信じている場合

また、:それは明らかに優れている質問のこれらの種類について

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