Question

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. 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.

Any tips? Thanks!

Was it helpful?

Solution 2

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.

Edit #1 (parsing it all, granting compliance with strict aliasing rules, and making you see that this does not make any sense):

#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

OTHER TIPS

Given:

the array contains {'9','9','9','0','1','1','1'}

Then you can convert with 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.

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

The print statement willl goes as follows..

ID is 009 Code is 8 Val is 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. Note there is no need to use compact because it is only 1 byte. This is C11 implementation. 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. 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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top