web-dev-qa-db-fra.com

Tableau de bits décalé de caractères

J'ai un tableau de caractères que j'essaie de modifier binaire >>, puis & avec un autre tableau. Je pense avoir mal compris la façon de procéder.

Je pensais que, même si c’était un tableau de caractères indiquant que my_array >>= 1 changerait tout, mais je reçois une erreur: "error: invalid operands to binary >> (have ‘char[8]’ and ‘int’)"

La comparaison au niveau du bit que j'essaie de faire est avec un tableau de taille similaire lancé à tous les "0" ... pour cela, je reçois: "error: invalid operands to binary & (have ‘char *’ and ‘char *’)"

Dois-je convertir ces tableaux en quelque chose d'autre avant de pouvoir changer et comparer?

Désolé, je n'étais pas très clair ... Tous les bons conseils à ce jour et je pense que je me rends davantage compte qu'il n'y a pas de moyen super facile de le faire. Plus précisément, ce que j'essaie de faire est de décaler les bits du tableau de caractères WHOLE à droite 1, en ajoutant le bit décalé de gauche à droite du tableau, faites la comparaison au niveau du bit avec un autre tableau de même taille.

Techniquement, la comparaison ne doit pas nécessairement être tableau avec tableau ... J'ai juste besoin des bits. Serait-il plus facile de convertir le tableau en quelque chose d'autre avant d'essayer de faire les décalages/comparaisons?

10
MCP

Vous devez déplacer et comparer élément par élément.

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

par exemple. Si vous voulez déplacer les bits décalés d’un élément à l’autre, c’est plus compliqué, disons que vous décalez correctement, puis

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;
}

traverser le tableau dans l'autre sens car vous avez besoin des bits de l'emplacement le plus proche.

12
Daniel Fischer
/** 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.
        }   
    }
}   
3
Richard Pennington

Vous devrez déplacer les entrées dans le tableau une par une. (Et si vous voulez comparer deux d'entre eux, vous devrez le faire élément par élément.)

Si vous espériez que les bits décalés de chaque caractère seraient décalés dans le suivant, vous devrez également vous en occuper manuellement.

Si vous souhaitez adopter ce comportement, et que cela ne vous dérange pas de rendre votre code méchant, non portable et sujet aux bogues, vous pourrez peut-être placer un pointeur sur le tableau et le convertir en unsigned long long * , déréférencez-le et déplacez-le, puis enregistrez-le à nouveau.

MAIS si c'est le comportement que vous voulez, vous devriez utiliser un entier au lieu d'un char[8] pour commencer.

(Si vous pouviez en dire plus sur ce que vous visiez réellement, des réponses plus utiles pourraient être possibles.)

2
Gareth McCaughan

Si vous souhaitez effectuer des opérations telles que le déplacement de/OR/XOR/AND/etc .. sur des tableaux, vous devez l'exécuter en boucle, vous ne pouvez pas l'exécuter directement sur le tableau. .

2
MByD

Vous pouvez déplacer uniquement les membres de ces tableaux, un caractère (ou un int). Vous ne pouvez pas déplacer un tableau entier. Décalage my_array tente d'effectuer une opération de décalage sur un type de tableau (ou un pointeur sur char), ce qui est impossible. Faites ceci à la place:

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

De plus, vous devez être prudent avec les caractères car ils sont généralement signés, et un caractère contenant une valeur négative apportera "1" à gauche au lieu de zéros. Donc, vous feriez mieux d'utiliser des caractères non signés.

EDIT: Le code ci-dessus est simpliste. Si vous vouliez déplacer le tableau dans son ensemble, pas seulement chaque octet, vous devez alors copier "manuellement" chaque LSB dans le bit de poids fort de l'octet à sa droite. Prenez une boucle à la réponse de Richard Pennington.

2
Israel Unterman

Je sais que c'est un sujet ancien, mais je n'étais pas satisfait des réponses disponibles. Voici quelque chose que j'ai écrit récemment et qui vous permet de spécifier le nombre de bits que vous pouvez déplacer. Il existe également un cryptage simple 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);
    }
}
0
Ashvin Bhuttoo
/**
 * 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;
    }
}
0
boortmans