-1
#include <iostream>
#include <bitset>

typedef struct
{
    int i;
    char a[4];
    uint8_t j:1;
    uint8_t k:1;
} abctest;

int main()
{
    abctest tryabc;
    memset(&tryabc, 0x00, sizeof(tryabc));
    std::bitset<1> b;
    b = false;
    std::cout << b << '\n';
    b = true;
    std::cout << sizeof(b) << '\n';
}

My doubt is like I have a char array, it is basically a structure received in some module, in this structure I have bit fields also, I can use memcpy but I cannot Type cast the buffer to structure (for e.g if my char* arr is actually of type struct abc, I cannot do abc* temp = (abc*)arr) All I can do is memcpy only, So I want to know with out type casting how I can fill the bit fields.

Dilip Kumar
  • 1,736
  • 11
  • 22
  • Copying memory to the private fields of the structure is highly risky and platform/implementation depended. Do not do it! Bitset gives you an interface to filling it up. Use it instead! – W.F. Mar 20 '15 at 09:12
  • So why don't you use `memcpy` — `abc temp; memcpy(&temp, arr, sizeof(temp));`? – molbdnilo Mar 20 '15 at 09:44
  • I would `union` `k` and `j` to a `uint8_t`named `kj`. Then I can use `*((char*)arr + offsetof(abctest, kj)) = 0x0;` to set bits of both of them. – user3528438 Mar 20 '15 at 13:08

2 Answers2

0

Why can't you typecast a char array into an abctest pointer? I tested it and all works well:

typedef struct
{
    int i;
    char a[4];
    uint8_t j:1;
    uint8_t k:1;
} abctest;

int main(int argc, char **argv)
{
  char buf[9];
  abctest *abc = (abctest*)buf;
  memset(buf, 0x00, sizeof(buf));
  printf("%d\n", abc->j);
}

However, while you definitely CAN typecast a char array into an abctest pointer, it doesn't mean you SHOULD do that. I think you should definitely learn about data serialization and unserialization. If you want to convert a complex data structure into a character array, typecasting is not the solution as the data structure members may have different sizes or alignment constraints on 64-bit machine than on a 32-bit machine. Furthermore, if you typecast a char array into a struct pointer, the alignment may be incorrect which may result in problems using RISC processors.

You could serialize the code by e.g. writing i as a 32-bit integer in network byte order, a as 4 characters and j and k as two bits in one character (the rest 6 being unused). Then when you unserialize it, you read i from the 32-bit integer in network byte order, the a from 4 characters and the remaining character gives j and k.

juhist
  • 4,210
  • 16
  • 33
  • is thr any way to do without typecasting?? – Dilip Kumar Mar 20 '15 at 09:30
  • 1
    Yes, there is. Learn about data serialization! Unfortunately, I'm not going to write the data serialization and unserialization code for you, but if you have a 32-bit integer you can use bitshifts and bitmasks to get four 8-bit values out of it, which can be stored into a character array. Similarly, with bitshifts and bitwise OR, you can reconstruct the 32-bit integer from the four 8-bit values in the character array. Use an unsigned char array for data serialization; a char array would result in nasty signedness problems which can be remedied by typecasting into unsigned char. – juhist Mar 20 '15 at 09:35
  • 1
    what if `abc` violates alignment rule of `abctest`? your char `buf[9]` is `char` aligned and `abctest` requires `int` aligned. It' just UB that happens to work this time. – user3528438 Mar 20 '15 at 13:09
  • If abc violates the alignment rule of abctest and you are using a non-x86/AMD64 processor that demands proper data alignment, then you're screwed. Yet another reason to not do this kind of typecasting. However, if the character buffer is returned by malloc() then it's guaranteed to be properly aligned for all data types. I edited the answer to explain also that there may be alignment problems using this typecast. – juhist Mar 20 '15 at 13:14
0

If you know the literal data type and its size in bytes, a variable can be used with bit-shifting to store and extract bits into the array. This is a lower-level function that still exists in C++ but is more related to the low-level programming style of C.

Another way is to use the division and modulo with powers of 2 to encode bits at exact locations. I'd suggest you look up how binary works first and then figure out that shifting to the right by 1 actually divides by 2.

Cheers!

CinchBlue
  • 6,046
  • 1
  • 27
  • 58