0

I want to convert a struct to an array of bytes, and back again taking the bytes and converting/casting them to the struct.

here's some hypothetical code:

let's assume we have a struct foo

struct foo
{
  int x;
  float y;
} typedef foo;

assuming that we have already allocated some memory of 1000 bytes, i want to be able to put the bytes that the struct above represents into my already allocated 1000 bytes.

1
  • 1
    Unfortunately, you have accepted an incorrect answer—one that advises people to use code that improperly aliases an array of char as a structure, for which the behavior is not defined by the C standard. Commented Jan 15, 2019 at 3:28

4 Answers 4

4

How about memcpy(ptrToAllocedMemory, &structOnStack, sizeof(structOnStack));?

Sign up to request clarification or add additional context in comments.

2 Comments

"How about" you provide it? No need to be snarky, people are here to learn, and looking at memcpy as a function is an educational experience.
Sorry, not meant to be snarky. As I said, your code was correct. Just a little extra effort in trying to explain what you did and why will help not only the person asking the question now, but all those who are directed here in the years to come. For those who already know what you are talking about, nothing else is needed, but that in itself is the point. Your audience isn't those that already know how to code, but those who are trying to learn and who may not have heard of memcpy before.
2

Too convert a struct to an array of bytes ...

Simple assigned via a union. The members of foo will be copied with the assignment, perhaps any padding too. @Eric Postpischil

struct foo {
  int x;
  float y;
} typedef foo;

foo data_as_foo;

union x_foo {
  foo bar;
  unsigned char array_o_bytes[sizeof foo];
} x;

x.bar = data_as_foo;

// Do something with x.array_o_bytes
for (unsigned i = 0; i < sizeof x.array_o_bytes; i++) {
  printf("%2X ", x.array_o_bytes[i]);
}

An assignment is not even needed.

union x_foo = { .bar = data_as_foo );

What is important about return trip for bytes without alignment to foo is to use memcpy().

foo bytes_to_foo(const unsigned char *data) {
  foo y;
  memcpy(&y, data, sizeof y);
  return y;
}

If the bytes are aligned, as a member of union x_foo, than an assignment is sufficient.

union x_foo data_as_bytes;
// data_as_bytes.array_o_bytes populated somehow

foo data_as_foo = x_foo data_as_bytes.bar;

1 Comment

I rethought my comment, since I think you meant that assigning a union containing a member with no padding (the array of char) that fully covered a structure would necessarily copy all bytes corresponding to its structure. I would have to think about what wiggle room the standard affords. C allows reinterpreting bytes through a union, but that might not mean it has to treat all members in the union as possibly “existing,” rather than just the last one stored. So, if an implementation knows a structure was last stored, it might be permitted to omit its padding bytes in a union assignment.
0

You can simply make a pointer to the address, cast it and handle it from there.

A full code snipping demonstrating what you asked:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct foo
{
  int x;
  float y;
} typedef foo;

int main () {
        char *mem = malloc(1000); // preallocated memory as requested
        foo bar; // initial struct
        bar.x = 10; // initialize struct
        bar.y = 12;

        char *ptr =(char*)(&bar); //cast a char ptr to bar's address
        memcpy(mem, ptr, sizeof(foo)); // copy it over

        foo *result = (foo *)(mem); // cast the memory to a pointer to foo
        printf("%d, %f\n", result->x,result->y); // and it works!

        return 0;
}

If you wanted to cast the pointer and copy it in one line, you could also do

memcpy(mem,(char*)(&bar), sizeof(foo));

For the same effect.

2 Comments

(foo *)(mem); works here as mem is assigned via malloc(). (foo *)(mem); can fail when the address of the byte data is not certainly aligned per foo needs.
a lot of this is unnecessary, you could just go foo *result = (foo *)mem; *result = bar;
0

All variables and struct in C are stored in memory, and memory is already array of bytes.

So, in contrast to Java or C#, you do not need to do any additional transformation:

// to get struct's bytes just convert to pointer
struct foo tmp;
unsigned char* byte_array = (unsigned char*)&tmp;

// from bytes to struct
_Alignas(struct foo) unsigned char byte_array2[sizeof(struct foo)];
struct foo* tmp2 = (struct foo*)byte_array2;

as people are pointing in comments - conversion from array to struct could lead to UB on some platforms, so its better to avoid it unless you allocated properly aligned block

7 Comments

Note: this does not "put the bytes that the struct above represents into my already allocated 1000 bytes", it simply assigns a pointer to the original.
@DavidC.Rankin is right, if you need "copy" - then of course you have to use memcpy
byte_array2; is not certainly aligned as needed for struct foo* leading to undefined behavior (UB) in the assignment.
struct foo* tmp2 = (struct foo*)byte_array2; is bad C code because the behavior of accessing an array of char through a struct foo lvalue is not defined by the C standard. (This assignment of the pointer may succeed, but subsequent use of the pointer to access the memory pointed to by tmp2 is improper.)
It is not true that all struct in C are stored in memory. Structures may be values without being lvalues.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.