如何清除C中无符号字符数组的位?

如何清除C中无符号字符数组的位?,c,bit-manipulation,C,Bit Manipulation,假设我有一个名为backup的无符号字符数组,我想在其中复制一些字节。但我想做的是清除大部分位(从右到左的18位)。我需要留下的是左边的两个位子。这是我的尝试: memcpy (buf, " AA", 3); unsigned char backup[3]; memcpy( backup, buf, 3 ); // backup int two_bits_backup; two_bits_backup = (int) backup &= ~0b0011111111111111111111

假设我有一个名为backup的
无符号字符
数组,我想在其中复制一些字节。但我想做的是清除大部分位(从右到左的18位)。我需要留下的是左边的两个位子。这是我的尝试:

memcpy (buf, " AA", 3);
unsigned char backup[3];
memcpy( backup, buf, 3 ); // backup
int two_bits_backup;
two_bits_backup = (int) backup &= ~0b001111111111111111111111;
但它会产生错误: 赋值的左操作数需要左值

如何成功清除这两个位

我要做的是清除这些位(粗体)

如果两位备份=0b111111111111

case two_bits_backup ==   0b110000000000000000000000;

我想将无符号字符数组转换为int,然后清除它


我在C和32位平台上使用它,其中int有4个字节。

您收到的错误消息是因为您试图为数组赋值。不能将数组作为一个整体分配给它,即使您尝试强制转换它

您需要分别对每个字节执行位清除,然后使用位移位将各个位放入
两个\u位\u备份中

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];
backup[0]&=~0x3f;
备份[1]&=~0xff;
备份[2]&=~0xff;

两位\u backup=backup[0]您收到的错误消息是因为您试图为数组赋值。不能将数组作为一个整体分配给它,即使您尝试强制转换它

您需要分别对每个字节执行位清除,然后使用位移位将各个位放入
两个\u位\u备份中

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];
backup[0]&=~0x3f;
备份[1]&=~0xff;
备份[2]&=~0xff;

两位备份=备份[0]另一种方法是使用备份作为指向int的指针:

two_bits_backup = *(int*)backup &= ~0b001111111111111111111111;
基于下面的评论,我要补充一点:备份的大小必须为[4](或更大),才能在大多数系统上正常工作,而不会违反别名规则

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

memcpy仍然可以工作,尤其是在n=3的情况下。“&”操作将处理上字节中可能的垃圾。

另一种方法是使用指向int的备份指针:

two_bits_backup = *(int*)backup &= ~0b001111111111111111111111;
基于下面的评论,我要补充一点:备份的大小必须为[4](或更大),才能在大多数系统上正常工作,而不会违反别名规则

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

memcpy仍然可以工作,尤其是在n=3的情况下。“&”操作将处理高位字节中可能出现的垃圾。

我不明白您到底想做什么。无符号字符是1字节。因此,如果要提取前2位,您应该使用1100 0000进行逻辑AND,并将6位右移

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

数组中的所有元素都是这样。

我不明白您到底想做什么。无符号字符是1字节。因此,如果要提取前2位,您应该使用1100 0000进行逻辑AND,并将6位右移

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

数组中所有元素的操作方法相同。

如果要使用字符数组来管理24位整数,可以用这种方法操作(对于little endian机器)。但是,天哪,这不是一个干净的方式

#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;
}
#包括
#包括
内部主(空)
{
无符号字符buf[3];
//备份应该是sizeof(unsigned int)字节,因为3字节的int不存在!
无符号字符备份[sizeof(unsigned int)];
无符号整数两位备份;
memcpy(buf,“AA”,sizeof(buf));
//memset(buf,0xD5,sizeof(buf));
memset(备份,0,sizeof(unsigned int));
memcpy(backup,buf,sizeof(buf));//备份
printf(“%08X\n”,*(未签名整数*)(备份));
两位备份=*(无符号整数*)(备份)和=~0B0011111111;
printf(“%08X\n”,两位备份);
返回0;
}

如果您想使用字符数组来管理24位整数,您可以这样操作(对于little endian机器)。但是,天哪,这不是一个干净的方式

#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;
}
#包括
#包括
内部主(空)
{
无符号字符buf[3];
//备份应该是sizeof(unsigned int)字节,因为3字节的int不存在!
无符号字符备份[sizeof(unsigned int)];
无符号整数两位备份;
memcpy(buf,“AA”,sizeof(buf));
//memset(buf,0xD5,sizeof(buf));
memset(备份,0,sizeof(unsigned int));
memcpy(backup,buf,sizeof(buf));//备份
printf(“%08X\n”,*(未签名整数*)(备份));
两位备份=*(无符号整数*)(备份)和=~0B0011111111;
printf(“%08X\n”,两位备份);
返回0;
}


如果
backup
是一个无符号字符数组,则不能将其视为
int
。(换句话说,
(int)backup
是非常错误的,它没有做任何你想做的事情。)你知道吗,a&=b是a=a&b的缩写?因此,您无法修改(int)备份,因为它是r值。代码中的
备份
不是
无符号字符*
。我不明白您在问什么。您能否提供示例输入/输出来演示所需内容?我想将无符号字符串数组转换为整数,然后清除22位。如果
backup
是无符号字符数组,您不能将其视为
int
。(换句话说,
(int)backup
是非常错误的,它没有做任何你想做的事情。)你知道吗,a&=b是a=a&b的缩写?因此,您无法修改(int)备份,因为它是r值。代码中的
备份
不是
无符号字符*
。我不明白您在问什么。您能提供示例输入/输出来演示您想要的内容吗?我想将无符号字符串数组转换为整数,然后清除22位,不要忘记将它们移到正确的位置以存储到整数中。@AndreKampling doneuselles/可能有害的强制转换。@AnttiHaapala您是对的,隐式转换应该解决这个问题。删除了强制转换。@dbush,除非变量不是易失性的,否则如果要赋值零,则需要3次操作(ARM gcc 6.3)。不要忘记将它们移到正确的位置,以将它们存储到整数中。@AndreKampling doneuselles/可能有害的强制转换。@AnttiHaapala您是对的,im