0
votes

Let's suppose I have unsigned char array called backup where I want to copy some bytes. But what I want to do is to clear most of the bits (18 bits from right to left). What I need to stay is the two bits on the left. This is my try:

memcpy (buf, " AA", 3);
unsigned char backup[3];
memcpy( backup, buf, 3 ); // backup
int two_bits_backup;
two_bits_backup = (int) backup &= ~0b001111111111111111111111;

But it generates error: lvalue required as left operand of assignment

How to clear the two bits successfully?

What I want to do is to clear these bits (bold)

in case two_bits_backup = 0b111111111111111111111111;

case two_bits_backup ==   0b110000000000000000000000;

I wanted to convert the unsigned char array to int and then to clear it.

I am using this on C and 32-bit platform, where int has 4 bytes.

4
If backup is an unsigned char array, you can't just treat it as if it's an int. (in other words, (int)backup is very wrong and it's not doing anything like what you want.)Steve Summit
do you know, that a&=b is short form for a = a & b? as the result you cannot modily (int)backup, because it is r-valueAnatolyS
The backup in your code is not an unsigned char *.melpomene
I don't understand what you're asking. Can you provide sample input/output that demonstrates what you want?melpomene
I wanted to convert the unsigned string array to integer and then to clear the 22 bitsJohn Boe

4 Answers

3
votes

The error message you're getting is because you're attempting to assign a value to an array. An array cannot be assigned to as a whole, even if you attempt to cast it.

You need to perform the bit clearing on each byte individually, then use bit shifting to put the individual bits into two_bits_backup

backup[0] &= ~0x3f;
backup[1] &= ~0xff;
backup[2] &= ~0xff;

two_bits_backup = backup[0] << 16;
two_bits_backup |= backup[1] << 8;
two_bits_backup |= backup[2];

Note that this assumes that the bytes in backup are most significant byte first with most significant bit first.

1
votes

the other way is to use backup a a pointer to int:

two_bits_backup = *(int*)backup &= ~0b001111111111111111111111;

based on the comments below, I am adding this note: the backup must be of size [4] (or more) to work properly on most systems without violation of aliasing rules.

char backup[4];
or 
char *backup = malloc(4);

memcpy still can work, as prviously with n= 3. The '&' operation will take care of possible trash in the upper byte.

0
votes

I didn't understand what you want to do exactly.Unsigned char is 1 byte.So You should make logical AND with 1100 0000 and shifting 6 bits right if you want to extract first 2 bits.

(backup[0] &= C0)>>6

The same way for all of the elements in the array.

0
votes

If you want to use a char array to manage a 24 bits integer, you may operate in this way (for little endian machine). But, IMHO, it's not a clean way.

#include <stdio.h>
#include <string.h>

int main(void)
{
    unsigned char buf[3];

    // Backup should be sizeof(unsigned int) bytes because an int of 3 bytes doesn't exist!
    unsigned char backup[sizeof(unsigned int)];
    unsigned int two_bits_backup;

    memcpy (buf, " AA", sizeof(buf));
    // memset (buf, 0xD5, sizeof(buf));

    memset( backup, 0, sizeof(unsigned int));
    memcpy( backup, buf, sizeof(buf) ); // backup

    printf("%08X\n",*(unsigned int *)(backup));

    two_bits_backup = *(unsigned int *)(backup) &= ~0b001111111111111111111111;

    printf("%08X\n",two_bits_backup);

    return 0;
}