简体   繁体   English

c中char数组的位操作

[英]Bit Manipulation on char array in c

If I am given a char array of size 8, where I know the the first 3 bytes are the id, the next byte is the message, and the last 3 bytes are the values.如果给我一个大小为 8 的字符数组,我知道前 3 个字节是 id,下一个字节是消息,最后 3 个字节是值。 How could I use bit manipulation in order to extract the message.我如何使用位操作来提取消息。

Example: a char array contains 9990111 (one integer per position), where 999 is the id, 0 is the message, and 111 is the value.示例:char 数组包含 9990111(每个位置一个整数),其中 999 是 id,0 是消息,111 是值。

Any tips?有小费吗? Thanks!谢谢!

Given:鉴于:

the array contains {'9','9','9','0','1','1','1'}数组包含 {'9','9','9','0','1','1','1'}

Then you can convert with sscanf() :然后您可以使用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);

But there's no bit manipulation needed there.但是那里不需要任何操作。

The usual way would be to define a structure with members which are bit fields and correspond to the segmented information in your array.通常的方法是定义一个结构,其成员是位字段并对应于数组中的分段信息。 (oh, re-reading your question: is the array filled with { '9', '9',...} ?? Then you'd just sscanf the values with the proper offset into the array. (哦,重新阅读您的问题:数组是否填充了{ '9', '9',...} ?? 然后您只需将具有适当偏移量的值扫描到数组中。

Well, if you want bit manipulation, no matter what, here it goes:好吧,如果你想要位操作,无论如何,这里是:

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

Output:输出:

7

Just remember one thing... this does not comply with strict aliasing rules.请记住一件事......这不符合严格的别名规则。 But you can use some memcpy() stuff to solve it.但是你可以使用一些 memcpy() 的东西来解决它。

Edit #1 (parsing it all, granting compliance with strict aliasing rules, and making you see that this does not make any sense):编辑 #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;
}

Output:输出:

999
7
111

You can use Memory Copy to extract the values.您可以使用内存复制来提取值。 Here is an example这是一个例子

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

Lets say string msgTest = "0098457让我们说字符串 msgTest = "0098457

The print statement willl goes as follows..打印语句如下..

ID is 009 Code is 8 Val is 457 ID 是 009 代码是 8 Val 是 457

Hope this helps, Good luck!希望这有帮助,祝你好运!

here is an example in which i don't use malloc or memory copy for a good implementation on embedded devices, where the stack is limited.这是一个示例,其中我不使用 malloc 或内存副本来在堆栈有限的嵌入式设备上实现良好的实现。 Note there is no need to use compact because it is only 1 byte.注意没有必要使用compact,因为它只有1 个字节。 This is C11 implementation.这是 C11 实现。 If you have 4 Bytes for example to be analyzed, create another struct with 4 charbits, and copy the address to the new struct instead.例如,如果要分析 4 个字节,请创建另一个具有 4 个字符位的结构,并将地址复制到新结构中。 This is coinstance with design patterns concept for embedded.这与嵌入式设计模式的概念是一致的。

#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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM