13

ビット単位で右にシフトしようとしているcharの配列があり>>、次に&別の配列を使用しています。私はこれを行う方法について間違った考えを持っていると思います。

私は、それが文字の配列であったとしても、my_array >>= 1すべてをシフトすると述べているだけだと思っていましたが、エラーが発生しています:"error: invalid operands to binary >> (have ‘char[8]’ and ‘int’)"

私が行おうとしているビット単位の比較は、すべての「0」に対して開始された同様のサイズの配列を使用することです...そのために私は次のようになります。"error: invalid operands to binary & (have ‘char *’ and ‘char *’)"

シフトして比較する前に、これらの配列を別のものに変換する必要がありますか?

申し訳ありませんが、私はあまり明確ではありませんでした...これまでのすべての素晴らしいアドバイスと私はこれを行うための超簡単な方法がないことをもっと認識していると思います。具体的には、char配列全体のビットを右に1シフトし、右からシフトしたビットを配列の左端に追加して、同じサイズの別の配列とビット単位で比較します。

技術的には、比較は配列と配列である必要はありません...必要なのはビットだけです。シフト/比較を行う前に、配列を別のものに変換する方が簡単でしょうか?

4

7 に答える 7

16

シフトして要素ごとに比較する必要があります。

for(i = 0; i < len; ++i)
    array[i] >>= 3;

例えば。ある要素から次の要素にシフトされたビットを移動したい場合は、より複雑です。たとえば、右にシフトしている場合は、

unsigned char bits1 = 0, bits2 = 0;
for(i = len-1; i >= 0; --i) {
    bits2 = array[i] & 0x07;
    array[i] >>= 3;
    array[i] |= bits1 << 5;
    bits1 = bits2;
}

次に高いスロットからのビットが必要なため、配列を反対方向にトラバースします。

于 2012-04-28T21:27:13.760 に答える
3
/** Shift an array right.
 * @param ar The array to shift.
 * @param size The number of array elements.
 * @param shift The number of bits to shift.
 */
void shift_right(unsigned char *ar, int size, int shift)
{
    int carry = 0;                              // Clear the initial carry bit.
    while (shift--) {                           // For each bit to shift ...
        for (int i = size - 1; i >= 0; --i) {   // For each element of the array from high to low ...
            int next = (ar[i] & 1) ? 0x80 : 0;  // ... if the low bit is set, set the carry bit.
            ar[i] = carry | (ar[i] >> 1);       // Shift the element one bit left and addthe old carry.
            carry = next;                       // Remember the old carry for next time.
        }   
    }
}   
于 2012-04-28T21:35:00.417 に答える
2

配列内のエントリを1つずつシフトする必要があります。(そして、これらの2つを比較したい場合は、要素ごとに行う必要があります。)

各文字からシフトオフされたビットが次の文字にシフトされることを期待している場合は、それも手動で処理する必要があります。

次のバイトへのシフト動作が必要で、コードを厄介で移植性がなく、バグが発生しやすいものにすることを気にしない場合は、配列へのポインターを取得して、のようなものにキャストできる可能性がありますunsigned long long *。それを逆参照し、結果の整数をシフトして、再度格納します。

ただし、それが必要な動作である場合は、最初にaの代わりに整数を使用する必要がありますchar[8]

(実際に達成しようとしていることについてもっと言えば、もっと役立つ答えが得られるかもしれません。)

于 2012-04-28T21:27:06.237 に答える
2

配列に対してシフト/OR/ XOR / AND /などの操作を実行する場合は、ループで実行する必要があります。配列に対して直接実行することはできません。

于 2012-04-28T21:27:31.387 に答える
2

その配列のメンバーであるchar(またはint)のみをシフトできます。配列全体をシフトすることはできません。Shiftingmy_arrayは、配列型(またはcharへのポインター)に対してシフト操作を実行しようとしますが、これは不可能です。代わりにこれを行ってください:

for (i = 0; i < size; i++) {
  my_array[i] >>= 1;
}

また、charは通常署名されているため、注意する必要があります。負の値を含むcharは、ゼロではなく左から「1」になります。したがって、unsignedcharsを使用することをお勧めします。

編集: 上記のコードは単純です。各バイトだけでなく、アレイ全体を右にシフトする場合は、各LSBをその右側のバイトのMSBに「手動で」コピーする必要があります。リチャードペニントンの答えでループを取ります。

于 2012-04-28T21:27:38.850 に答える
1
/**
 * shift a number of bits to the right
 *
 * @param   SRC         the array to shift
 * @param   len         the length of the array
 * @param   shift       the number of consecutive bits to shift
 *
*/
static void shift_bits_right(uint8_t SRC[], uint16_t len, uint32_t shift) {
    uint32_t i = 0;

    uint8_t start = shift / 8;
    uint8_t rest = shift % 8;
    uint8_t previous = 0;

    for(i = 0; i < len; i++) {
        if(start <= i) {
            previous = SRC[i - start];
        }
        uint8_t value = (previous << (8 - rest)) | SRC[i + start] >> rest;
        SRC[i + start] = value;
    }
}
于 2018-07-30T12:47:35.210 に答える
1

これは古いトピックですが、利用可能な回答に満足できませんでした。最近書いたもので、シフトできるビット数を指定でき、単純なXOR暗号化も含まれています。

//https://github.com/ashvin-bhuttoo/CryptoTest/blob/master/CryptoTest/Crypto.cpp
//CRYPTO CONFIGURATION PARAMETERS
#define BIT_SHIFT 3
#define XOR_KEY 0x3C
#define ENABLE_XOR_VARIANCE true
////////////////////////////////

int get_rs_mask(int shift)
{
    switch (shift)
    {
    case 0:
        return 0x00;
    case 1:
        return 0x01;
    case 2:
        return 0x03;
    case 3:
        return 0x07;
    case 4:
        return 0x0F;
    case 5:
        return 0x1F;
    case 6:
        return 0x3F;
    case 7:
        return 0x7F;
    default:
        throw "get_rs_mask -> Error, shift argument outside legal range 0-7";
    }
}

void shift_right(char* buf, int msg_len, int shift)
{
    unsigned char tmp = 0x00, tmp2 = 0x00;
    for (int k = 0; k <= msg_len; k++)
    {
        if (k == 0)
        {
            tmp = buf[k];
            buf[k] >>= shift;
        }
        else
        {
            tmp2 = buf[k];
            buf[k] >>= shift;
            buf[k] |= ((tmp & get_rs_mask(shift)) << (8 - shift));

            if (k != msg_len)
                tmp = tmp2;
        }
    }
}

int get_ls_mask(int shift)
{
    switch (shift)
    {
    case 0:
        return 0x00;
    case 1:
        return 0x80;
    case 2:
        return 0xC0;
    case 3:
        return 0xE0;
    case 4:
        return 0xF0;
    case 5:
        return 0xF8;
    case 6:
        return 0xFC;
    case 7:
        return 0xFE;
    default:
        throw "get_ls_mask -> Error, shift argument outside legal range 0-7";
    }
}

void shift_left(char* buf, int msg_len, int shift)
{
    char tmp = 0x00, tmp2 = 0x00;
    for (int k = msg_len; k >= 0; k--)
    {
        if (k == msg_len)
        {
            tmp = buf[k];
            buf[k] <<= shift;
        }
        else
        {
            tmp2 = buf[k];
            buf[k] <<= shift;
            buf[k] |= ((tmp & get_ls_mask(shift)) >> (8 - shift));

            tmp = tmp2;
        }
    }
}

void crypt(char* buf, int msg_len, bool decrypt = false)
{
    if (!decrypt)
    {
        shift_right(buf, msg_len, BIT_SHIFT);
        for (int k = 0; k < msg_len; k++)
        {
            buf[k] = buf[k] ^ XOR_KEY ^ k * (ENABLE_XOR_VARIANCE ? 2 : 0);
        }
        buf[msg_len] = '\0';
    }
    else
    {
        for (int k = 0; k < msg_len; k++)
        {
            buf[k] = buf[k] ^ XOR_KEY ^ k * (ENABLE_XOR_VARIANCE ? 2 : 0);
        }
        shift_left(buf, (msg_len)-1, BIT_SHIFT);
    }
}
于 2018-12-14T07:01:08.327 に答える