c中char数组的位操作

时间:2014-05-07 05:19:27

标签: c bit-manipulation

如果给出一个大小为8的char数组,我知道前3个字节是id,下一个字节是消息,最后3个字节是值。我怎么能使用位操作来提取消息。

示例:char数组包含9990111(每个位置一个整数),其中999是id,0是消息,111是值。

任何提示?谢谢!

5 个答案:

答案 0 :(得分:4)

假设:

  

数组包含{'9','9','9','0','1','1','1'}

然后您可以使用sscanf()转换:

char buffer[8] = { '9', '9', '9', '0', '1', '1', '1', '\0' };
//char buffer[] = "9990111";  // More conventional but equivalent notation
int id;
int message;
int value;

if (sscanf(buffer, "%3d%1d%3d", &id, &message, &value) != 3)
    …conversion failed…inexplicably in this context…
assert(id == 999);
assert(message == 0);
assert(value == 111);

但那里不需要任何操作。

答案 1 :(得分:0)

通常的方法是定义一个结构,其成员是位字段,对应于数组中的分段信息。 (哦,重新阅读你的问题:数组是否填充了{ '9', '9',...} ??然后你只需要在数组中使用适当的偏移量来扫描这些值。

答案 2 :(得分:0)

好吧,如果你想要位操作,无论如何,这里都是:

#include <stdio.h>
#include <arpa/inet.h>

int main(void) {
        char arr[8] = "9997111";
        int msg = 0;

        msg = ((ntohl(*(uint32_t *) arr)) & 0xff) - 48;

        printf("%d\n", msg);

        return 0;
}

输出:

7

记住一件事......这不符合严格的别名规则。但你可以用一些memcpy()来解决它。

编辑#1(解析所有内容,允许遵守严格的别名规则,并让您看到这没有任何意义):

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <arpa/inet.h>

int main(void) {
        char arr[8] = "9997111";
        uint32_t a[2];
        unsigned int id = 0, msg = 0, val = 0;

        memcpy(a, arr, 4);
        memcpy(&a[1], arr + 4, 4);

        a[0] = ntohl(a[0]);
        a[1] = ntohl(a[1]);

        id = ((((a[0] & 0xff000000) >> 24) - 48) * 100) + ((((a[0] & 0xff0000) >> 16)- 48) * 10) + (((a[0] & 0xff00) >> 8)- 48);
        msg = (a[0] & 0xff) - 48;
        val = ((((a[1] & 0xff000000) >> 24) - 48) * 100) + ((((a[1] & 0xff0000) >> 16)- 48) * 10) + (((a[1] & 0xff00) >> 8)- 48);

        printf("%d\n", id);
        printf("%d\n", msg);
        printf("%d\n", val);

        return 0;
}

输出:

999
7
111

答案 3 :(得分:0)

您可以使用“内存复制”来提取值。这是一个例子

    char *info = malloc(sizeof(int)*3);
    char *info2 = malloc(sizeof(int)*1);
    char *info3 = malloc(sizeof(int)*3);

    memcpy(info,msgTest, 3);
    memcpy(info2,msgTest+3, 1);
    memcpy(info3,msgTest+4, 3);
    printf("%s\n", msgTest);
    printf("ID is %s\n", info);
    printf("Code is %s\n", info2);
    printf("Val is %s\n", info3);

让我们说字符串msgTest =&#34; 0098457

print语句将如下所示..

ID为009 代码是8 Val是457

希望这有帮助,祝你好运!

答案 4 :(得分:0)

这是一个示例,其中我不使用 malloc 或内存复制来在堆栈有限的嵌入式设备上实现良好的实现。注意没有必要使用 compact 因为它只有 1 个字节。这是 C11 实现。例如,如果要分析 4 个字节,请创建另一个具有 4 个字符位的结构,并将地址复制到新结构中。这与嵌入式设计模式的概念是一致的。

#include <stdio.h>

// start by creating a struct for the bits
typedef struct  {
    unsigned int bit0:1; //this is LSB
    unsigned int bit1:1; //bit 1
    unsigned int bit2:1;
    unsigned int bit3:1;
    unsigned int bit4:1;
    unsigned int bit5:1;
    unsigned int bit6:1;
    unsigned int bit7:1;
    unsigned int bit8:1;
}charbits;


int main()
{
    // now assume we have a char to be converted into its bits
    char a = 'a'; //asci of a is 97
    charbits *x;   //this is the character bits to be converted to
    // first convert the char a to void pointer
    void* p; //this is a void pointer
    p=&a;    // put the address of a into p
    //now convert the void pointer to the struct pointer
    x=(charbits *) p;

    // now print the contents of the struct
    printf("b0 %d b1 %d b2 %d b3 %d b4 %d b5 %d b6 %d b7 %d", x->bit0,x->bit1, x->bit2,x->bit3, x->bit4, x->bit5, x->bit6, x->bit7, x->bit8);

    // 97 has bits like this 01100001
    //b0 1 b1 0 b2 0 b3 0 b4 0 b5 1 b6 1 b7 0 
    // now we see that bit 0 is the LSB which is the first one in the struct

    return 0;
}
    // thank you and i hope this helps