?
Solved

How to convert struct into a byte array?

Posted on 2003-03-06
7
Medium Priority
?
610 Views
Last Modified: 2010-07-27
I have the following struct:
typedef struct T_MDM_COMMAND
{
    COMMAND_CODE ccode;
    unsigned char target_cpu;
    unsigned int POSIX_id;    
    unsigned int data_size;  
    char *data;              

} MDM_COMMAND;

typedef union T_COMMAND_CODE
{
    unsigned long code;
    struct CODE_BREAKUP
    {
        unsigned char sending_cpu;
        unsigned char cmd_type;
        unsigned char sending_thread;
        unsigned char cmd;
    };
} COMMAND_CODE;

What is the best way to write this struct into a byte array? One of the ways is just use pointers and their incrementation. Could you help me to do to it more efficient? Any predefined functions in C++ could help.
Thanks in advance,
alinashamk

0
Comment
Question by:alinashamk
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
7 Comments
 
LVL 12

Expert Comment

by:Salte
ID: 8081513
If you just want to view the data as a byte array - so that you can call functions that take byte arrays as arguments you can simply do this:

(const char *) & struct_var;

if a function to write the data takes arguments like this:

write_data(const char * buf, int len);

you can call it like this:

MDM_COMMAND mdm;

write_data((const char *) & mdm, sizeof(mdm));

Be aware that this is only useful for a binary stream - either a binary file or some communication channel which handles binary data. Sending this kind of data to a text stream will probably not work very well.

Often a function to write any type of data is declared as:

write_data(void * buf, size_t sz);

in this case you don't have to cast, since any pointer type can convert to void * type:

write_data(& mdm, sizeof(mdm));

should work, whatever the struct variable or other type of data mdm might be. The only time when this wouldn't work is if mdm itself is a pointer to the data and not the data itself or if mdm is an array:

if mdm is a pointer instead, then you need to have the size some other place:

write_data(pmdm, sizeof(*pmdm));

would work if pmdm is a pointer to a single mdm data element.

write_data(pmdm, sz);

must be used if pmdm is a pointer to an array of mdm data and sz is the size of the data or num * sizeof(*pmdm) can be used if you have a count of elements instead of size.

If mdm is an array, then this should work:

write_data(mdm, sizeof(mdm));

since an array is a pointer to the first element you don't use & mdm in this case.

Alf
0
 

Author Comment

by:alinashamk
ID: 8081984
Salte,
First of all, thank for your quick and detailed response.
The purpose of the project is to manually convert struct into a byte array and then send it through a TCP/IP connection to another board. We will run it on RTOS
If you will be kind enough to see if there are additional tricks that can be used, I will appreciate it.
Thanks in advance,
alinashamk
0
 

Author Comment

by:alinashamk
ID: 8082199
Salte,
First of all, thank for your quick and detailed response.
The purpose of the project is to manually convert struct into a byte array and then send it through a TCP/IP connection to another board. We will run it on RTOS
If you will be kind enough to see if there are additional tricks that can be used, I will appreciate it.
Thanks in advance,
alinashamk
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 12

Expert Comment

by:Salte
ID: 8082266
as far as I know the send() functions are usually declared wiith void * pointers to the buffer, if they aren't just cast the pointer to (char *) or (const char *) as appropriate. Possibly using reinterpret_cast<char *>(& mdm) or reinterpret_cast<const char *>(& mdm) instead of the C style cast.

Another way would be to just declare something like:

union {
   MDM_COMMAND mdm;
   char buf[sizeof(mdm)];
};

mdm.foo = bar;
send(buf,sizeof(mem));

That works as well.

Again, if send is declared to take void * buf as it should such a union isn't necessary and you just send the address to the struct as the argument.

This also works the other way, if you have a char buffer and you know that starting at index 16 the MDM_COMMAND buffer is residing you can do:

char buf[100];

MDM_COMMAND * pmdm = reinterpret_cast<MDM_COMMAND *>(pmdm + 16);

mdm.foo = pmdm -> foo;

or even:

memcpy(& mdm, buf + 16, sizeof(mdm));

will copy the whole struct to mdm. Note that this won't work very well if mdm is a class or struct with virtual functions or with pointers (char * members etc). The reason is that this will copy the whole struct or class is copied bit for bit. For one thing, you should never send such a class or struct to another machine since pointers in the sneding process doesn't mean anything to the receiving process. It doesn't help you to know that the source struct had a string stored in address 0x4445560 at the source process, you can't use that address to retrive the string unless you sent another request to that process and asked it what is the string at address 0x4445560. However, allowing for this would be a HUGE security whole where a process could read any data from anywhere in your memory by just sending a random value and ask what is there.

So in general you don't have such discussion between the processes about pointers, you don't transfer pointers period - at least not as pointers.

The same thing with virtual table pointer if the class or struct had virtual functions. In this case you would definitely cause havoc for your own code when you overwrite your own class object's vtable pointer with the vtable pointer from the other process. Again, structs that are sent between processes should be 'dumb structs' with no virtual functions and no pointers. Given this restriction the above code properly copies the struct.

For the same reason you are also careful in what you send to another process, especially when sending structs. Avoid any pointers and no virtual functions in that struct. If you need virtual functions and pointers have a class outside that contain those stuffs and then when sending the data, translates them to a dumb struct which is then transferred over.

Alf
0
 

Author Comment

by:alinashamk
ID: 8082422
Alf,
Thanks for all your help.
My initial reaction was to use mem copy as well, but some of the engineers disagreed with me.
Your help is appreciated.
Thanks again.
0
 
LVL 12

Accepted Solution

by:
Salte earned 200 total points
ID: 8082583
If you just want to send the data or reference the data they can stay in the buffer and you don't need to memcpy.

Just set a pointer to point to them.

If the buffer goes away and you need to copy the data then you need to copy them. You can either use struct copy or memcpy, it doesn't make that much difference actually unless the struct is very small.

If the struct is very small, struct copy can be faster (depending on the implementation) but for large structs, the struct copy is implemented by using memcpy so they're the same. It is also possible that for your platform memcpy is used for all struct copies and so then too they are the same.

For small structs if the compiler is smart it can do special handling. If the sizeof(S) == sizeof(int) it can copy the struct as an int etc. In that case struct copy is faster than memcpy since memcpy is a generic function that can handle any size.

Alf
0
 

Author Comment

by:alinashamk
ID: 8082666
The response was quick and detailed. It was my first experience and left me fully satisfied. Thanks for giving me this opportunity.
0

Featured Post

Enroll in August's Course of the Month

August's CompTIA IT Fundamentals course includes 19 hours of basic computer principle modules and prepares you for the certification exam. It's free for Premium Members, Team Accounts, and Qualified Experts!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
Suggested Courses

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question