7

I am trying to convert my struct into a char*, and then back to a struct. But I guess I am missing something. Once it is returned to struct, only one attribute of the struct is correct. The rest is all wrong. Here is my code.

#include <iostream>

using namespace std;

struct INFO {
    unsigned char a;
    int b;
    int c;
    char g[121];
}inf;



int main () {
    char frame[128];

    INFO test1 = INFO();
    test1.a='y';
    test1.b=4000;
    test1.c=9000;
    strcpy(test1.g, "Goodbye World");

    sprintf(frame,(char*)&test1);

    INFO test2 = INFO();
    memcpy((char*)&test2, frame, sizeof(frame)); //shouldn't test2 have test1 values?

    cout << test2.a<<"\n";
    cout << test2.b<<"\n";
    cout << test2.c<<"\n";
    cout << test2.g<<"\n";
    getchar();
    return 0;
  }

Output:

y
-858993460
-858993460
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠

Only test2.a is correct. Am I converting it to a char* wrong, or is it the way I convert it back? Thanks

rex
  • 319
  • 2
  • 4
  • 10
  • Apart from being dreadful, you would do well to consider both the involved padding, and subsequently declaring `frame` as `char frame[sizeof(struct INFO)];` In fact, *print* that size at the top of your program, just for kicks. You're also using `sprintf()`, utterly wrong for "printing" to `frame`. The moment it runs into a zero-byte it will stop sending data (and you have plenty of zero-bytes in `b` and `c`). Finally, my curiosity for the purpose of the unused global variable `inf` is killing me. – WhozCraig Oct 05 '13 at 19:04
  • 2
    sprintf is not a memory copy – Adam Oct 05 '13 at 19:08
  • snprintf(output,payloadsize , "%d%d%d%d",i,j,k,l) – Alex Punnen Aug 24 '15 at 10:20
  • ╠ is 0xCC in codepage 437, and [MSVC fills 0xCC to uninitialized memory to help debugging](https://stackoverflow.com/q/370195/995714). That means you've accessed uninitialized memory. You can find tons of questions about ╠ and 0xCC here on SO – phuclv Aug 18 '18 at 10:56

2 Answers2

9

There are a few problems with this code, but the one that's causing the problem is the use of sprintf to copy binary data from the struct to the character array: if there's a NUL byte anywhere in the struct's data the copy will stop short. In this case there's a NUL char in the struct data right after the first member, either embedded in the second member or because of padding, so only the first member is copied entirely.

Use memcpy instead of sprintf.

// sprintf(frame,(char*)&test1); <-- wrong
memcpy(frame, &test1, sizeof(frame));

INFO test2 = INFO();
memcpy(&test2, frame, sizeof(frame));

Another problem is that the size of the INFO structure is likely not 128 because of padding and alignment, so it cannot be copied entirely to frame. Use the sizeof operator to find the size.

Joni
  • 108,737
  • 14
  • 143
  • 193
  • 1
    There's also absolutely no need to cast to `char*`. `memcpy` takes a `void*`. – sfstewman Oct 05 '13 at 19:08
  • 1
    Why copy sizeof(frame)? Shouldn't that be sizeof(INFO)? It'd make a lot more sense if OP just did `memcpy(&test2, &test1, sizeof(INFO));` – Brandon Oct 05 '13 at 19:08
  • 1
    @CantChooseUsernames, that would be a buffer overflow because here `frame` is smaller than `INFO`. – Joni Oct 05 '13 at 19:12
  • Thanks Joni it works! I know the rest of code looks bad, but it was a toy program I threw together quickly to inquire about my real problem. Thanks again! – rex Oct 05 '13 at 19:16
3
char frame[sizeof(INFO)]; // Let compiler decide size of frame

INFO test1 = INFO();
test1.a='y';
test1.b=4000;
test1.c=9000;
strcpy(test1.g, "Goodbye World");

memcpy(frame, &test1, sizeof(INFO)); // copy memory and not string
Iuri Covalisin
  • 645
  • 4
  • 7