convert structure to array of chars

Started by
6 comments, last by Zahlman 16 years, 2 months ago
Is there an easy way to convert a structure into an array of chars, perhaps some sort of standard library function?
Advertisement
It depends on what's in the structure. A simple "shallow copy" can be done by reading the memory of the structure. This is generally not a good idea though, as any future changes to the structure will break all stored instances of the structure.

What you want to do is usually referred to as "serialization." Now that you have a good term for google, you can probably get some good hits. When I want to serialize and unserialize, I make serialize and unserialize methods that use the fstream read and write methods for each data member. It's not great, and becomes a hassle for large structures, but it works.
Quote:Original post by rajend3
Is there an easy way to convert a structure into an array of chars, perhaps some sort of standard library function?
What language? And what is the array of characters supposed to represent exactly? (That is, are you looking for a string representation, raw bytes, or something else?)
Sure, just use memcpy.

struct SuperStruct{    int num1;    int num2;};SuperStruct newStruct;newStruct.num1 = 1;newStruct.num1 = 2;char* buffer = new char [sizeof(SuperStruct)];memcpy( buffer, &newStruct, sizeof(SuperStruct) );


HOWEVER, you have to be very careful when doing this sort of thing.

1. You need to make sure that the buffer you're copying into is big enough to hold all of the data you're going to copy there. In my code, I ensure this because I allocate the buffer right then and there. If you memcpy into a buffer that's too small, you're causing a buffer overrun and corrupting heap or stack memory (which will cause Very Bad things to happen). This also means performing checks on user input, so that a malicious user can't use your app to intentially cause a buffer overrun.

2. Depending on your struct definition and the platform you've compiled for, the data may not come out the way you expect it to. For example on a 32-bit x86 processor, data types need to be aligned on natural boundaries. This means 32-bit int's go on 4-byte boundaries, short's go on 2-byte boundaries, etc. If you mix types in your struct, you may end up with some "extra space" (known as padding bytes) that will be copied into your buffer. For example take this struct:

struct PaddedStruct{    int num1;    short num2;    int num3;}


This sum of the number of bytes in the types found in that struct is 10 (4+4+2), but the actual size of the struct you would get with sizeof is 12 bytes. This is because 2 padding bytes would be placed after the short, so that num3 comes out on a 4-byte boundary.

3. Be careful what you do with this data, especially for serialization. Don't expect to be able to store that data in a file or send it over a network and have a program running on a different platform be able to reconstruct your struct (due to alignment and endian issues).
For extra evil points you could access the struct storage directly.

typedef struct{    char    c;    int     i;} test_t;int main(void){    int i;    test_t test = {'x', 42};    unsigned char *bytes = (unsigned char *)&test;    for (i = 0; i < sizeof test; i++)        DoSomethingWith(bytes);        return 0;}


Don't.
Thanks for the help, I'll look into the possible methods, I'm not sure which one I'll use yet.
Keep in mind that pointers and array members of the struct may not be treated as you expect (or maybe they will)

ie
struct A
{
const char *p;
shared_ptr< A> ap;
void (*call_back)( int);
}

Also if its c++ style - then the vtable pointer is not going to be referential between sessions.

If the goal is to compute a hash value of the struct for the life of the process these limitation may be ok.

If its for serialisation you probably want something more sophisticated that includes stuff like schema'd versioning and that handle cyclical references.
Stop. Why do you think you want to do this?

This topic is closed to new replies.

Advertisement