简体   繁体   中英

Treat char array (or some bytes) as a struct object. How does it work?

I've seen technique treating a char array as a struct/class and operate on it directly. See the following pseudo example:

Struct Container {
    char e1;
    short e2;
    int e3;
    Class4 e4;
    Class5 e5;
    // more...
}

char *msg = char[SOME_SIZE];
// Fill up the msg with some bit stream.

// Then we treat the char array as struct.
Container *ctn = reinterpret_cast<Container *>(msg);
int v3 = ntohl( ctn.e3 );
short v4 = ctn.e4.toValue();    // Call methods of Class4 to output proper value.
int v5 = ctn.e5.toValue();

Question is when would this technique work? ie the requirements on the struct and its members. Clearly the biggest question is when the Container has struct/class objects like e4 and e5. Btw, I wanna use it in Linux.

And I wonder when would memory alignment come into play for this usage?

Would appreciate it if there's a good article to refer to.

Re @ben's comment. The use case I saw was receiving messages from a socket, where the message format is well defined. Think the motive here is need for speed. With this technique, we don't need to copy any fields in order to populate them into structs, just use them directly. This saves some memory and CPU time.

I was thinking how we handle the alignment though.

Question is when would this technique work?

It works when the character buffer holds a valid Container object (which means all the data members and bases have to be valid too, recursively) that's properly aligned (ie address is a multiple of alignof (Container) .

Generally, getting a valid object in there means using placement new , but in multi-process code - when receiving/accessing the object over IPC mechanisms - you should be wary of things like:

  • references or pointers (including pointers to the Virtual Dispatch Table), as they won't generally be set to something meaningful in the virtual address space of your own application (unless the other process eg pins a memory mapped segment at the same hardcoded virtual address),

  • file/socket descriptors, resource ids, reference counts etc. that may not be valid in your process,

  • endianness, 32-bit vs 64-bit sizes, alignment and padding differences between systems,

  • cleanup actions such as object deregistration from observers or management objects that don't make sense if the object wasn't actually created in your process.

Most of it's common sense - easy enough at the POD end of the scale and rarely worth it (over proper serialisation/deserialisation) at the complex-object end.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM