1. ## Structure definition

I have a character array that contains information that I want to populate into a structure. The array has the following data
0x01 0x7b 0xC0 0x08
How do I write a structure that will retreive information from this array in the following manner -->

the first three bits contain information a
the next 5 bits contain information b
the next 12 bits contain information c
the next 12 bits contain information d

typedef struct
{
unsigned long a : 3; // (0 for data given above)
unsigned long b : 5; // (1 for data given above)
unsigned long c : 12; // (7bc for data given above)
unsigned long d : 12; // (8 for data given above)
} Data;

does not seem to work. I work on an intel machine. Appreciate any help.

2. There's no standard way to write to your pre-defined structure. You can use memcpy but that will swap your bytes. However, the most portable way to do it is to shift to each field individually like this:

Code:
```#include <stdio.h>

typedef struct
{
unsigned int a : 3; // (0 for data given above)
unsigned int b : 5; // (1 for data given above)
unsigned int c : 12; // (7bc for data given above)
unsigned int d : 12; // (8 for data given above)
} Data;

int main()
{
Data d;
unsigned int i;
unsigned char a[4] = {0x01, 0x7b, 0xc0, 0x08};

i = a[0] << 24 | a[1] << 16 | a[2] << 8 | a[3];
d.a = i >> (32 - 3) & 0x07;
d.b = i >> (32 - 3 - 5) & 0x1f;
d.c = i >> (32 - 3 - 5 - 12) & 0xfff;
d.d = i & 0xfff;

printf("a = %x\nb = %x\nc = %x\nd = %x\n", d.a, d.b, d.c, d.d);

return 0;
}```

3. I tried this out and it works great ... thanks ... But I have another request. Can I acheive the result to this problem without so many shifting operations by just reshuffling the order of members in my structure?

1) I am not allowed to change the ordering of the bytes in the char array because another application uses this.
2) But I am allowed to change the ordering of the structure itself.
3) This said, I can copy over the data to another array temporarily and performing swab operations and bit reversals.

4. What function are you trying to use to copy it over? Shifting is still the best way to go. You have control over the way it copies and it's portable.

5. I use memcpy to copy between character arrays. I dont want to use the shifting route because that will mean that I need to know size of each data type. I prefer to change the structure itself so that it gets aligned into the right fields by virtue of the position of the field in the structure. Is this possible? This code need not be portable outside of the intel platform which is why I am okay with changing the structure itself.

This is what I need to do -->

1) get the data in as a character array .. this array contains info as in example character array ...
2) I then need to cast to a structure that contains a,b,c,d etc...
3) I then use this structure from now on to get values of a/b/c/d
4) Now if I create an instance of this structure and populate it with values, then memcpying this structure to a char array should give me back the array as shown in the example.

6. I'm not sure if it's possible to memcpy directly from an array to your structure without totally changing the way your structure looked. Because memcpy swap bytes when you do a copy, you'll get your bits split up between fields.

I suggest you write a couple of generic functions to copy from a char to a structure and a structure to a char. Pass in 4 fields. The source, destination, array of field sizes, and size of array.

7. When you say drastically change the structure, do you mean the sizes also ... because I am ok to changing the structures ... This structure is local to my application. its only the char array that goes out that will have to be consistent. Normally I dont do a memcpy I just directly cast.

char a[4]={0x01, 0x7b, 0xc0, 0x08};
...
...

Data * pData = (Data*) str;
pData->a ...
pData->b ...

Now is it possible to define a structure that will get data into the members as expected. Obviously I amassuming that the size of fields cannot change because you have to manipulate all four bytes and they are filled to max capacity.

Greatly Appreciate your help ... thanks once again

8. Actually, you can just use direct assignment. The only thing you need to keep in mind is that where you're assigning to may not have as many bits as the data being copied. Anyway, if you already know what the values are, just do:

d.a = a[0];
d.b = a[1];
d.c = a[2];
d.d =a[3];

There is no need to mask here. You have the end valus, just assign them.

Quzah.

9. He can't use direct assignment because some of the fields are less than 8 bits and some require bits from 2 array slots.

If you want to be able to use memcpy, you'll have to figure out on a case-by-case basis on how to define your structure. This requires a lot more work than shifting the values yourself.

10. He can't use direct assignment because some of the fields are less than 8 bits and some require bits from 2 array slots.
Yes, you can. The only warning you'll get (read that again: warning, not error) is that some truncation may occur.

If the assigned value falls in the number of bits that the lvalue contans, it'll work fine.

Perhaps you should try it yourself. It will work. If the value in X only uses the first N bytes, where N is the number of bits in the lvalue you're assigning to, you will have a prefect assignment. (IE: No data loss.)

If however, you are assigning a value that contains a higher number, you'll get truncation.

Can you say "type cast"? I thought you could! This is the exact same thing as a type cast. You can typecast an int to a char, but you may run into truncation.

It's as simple as that.

Quzah.

11. Yes you can do that but you would get incorrect results. Maybe you're misunderstanding what he wants.

If we do it the way you suggest:
Code:
```#include <stdio.h>
#include <string.h>

typedef struct
{
unsigned int a : 3; // (0 for data given above)
unsigned int b : 5; // (1 for data given above)
unsigned int c : 12; // (7bc for data given above)
unsigned int d : 12; // (8 for data given above)
} Data;
int main()
{
Data d;
unsigned char a[4] = {0x01, 0x7b, 0xc0, 0x08};

d.a = a[0];
d.b = a[1];
d.c = a[2];
d.d = a[3];

printf("a = %x\nb = %x\nc = %x\nd = %x\n", d.a, d.b, d.c, d.d);

return 0;
}```
Output:
a = 1 (should be 0)
b = 1b (should be 1)
c = c0 (should be 7bc)
d = 8

Anyway, if you already know what the values are
He doesn't know what the values are though. Depending on what the values are, the way the chars are assigned will be different.

Since that first field is only 3 bits, it'll take the first 3 bits and then the next 5 bits of a[0] will go in the next field.

12. Output:
a = 1 (should be 0)
b = 1b (should be 1)
c = c0 (should be 7bc)
d = 8

Oh really? How do you figure:

unsigned char a[4] = {0x01, 0x7b, 0xc0, 0x08};

The only one that gives you problems is the second one. Want to know why?

2|4|8|16|32 is NOT able to store 123. You cannot pack six bits into the space for five.

I am not wrong here. The output is exactly the way it should be. You cannot fix six bits into the space of five. Period.

printf("%d", 0x7b );

Understand the problem?

Quzah.

13. I understand what you're saying quzah. But that's not what he wants.

This structure is 32 bits.
unsigned int a : 3;
unsigned int b : 5;
unsigned int c : 12;
unsigned int d : 12;

Now in his char array {0x01, 0x7b, 0xc0, 0x08} also contains 32 bits.
He wants to put those 32 bits into the 32 bits of the structure while keeping the bit order.
the first three bits contain information a
the next 5 bits contain information b
the next 12 bits contain information c
the next 12 bits contain information d
So a = the first 3 bits of 0x01 which is 000b
b = the next 5 bits of 0x01 which is 00001b
and so on

14. Then you're all doing it the hard way.
Code:
```union x
{
struct
{
unsigned int a:3;
unsigned int b:5;
unsigned int c:12;
unsigned int d:12;
} a;
unsigned char b[4];
};

union x yz;

Apparently you have to assign them individually. In either case:

yz.b[0] = 0x01;
yz.b[1] = 0x7b;
yz.b[2] = 0xc0;
yz.b[3] = 0x08;
[/edit]```
Simplicity.

Quzah.

15. Unfortunately that would give you the same result as a memcpy.
If you printf a thru d you'll get:
a = 1
b = 0
c = 7b
d = 8c
Which is not what he wanted.

Although your memory location would contain the right bits.