5

I am trying to convert the following struct to a char array so that I can send it via the serial port.

struct foo
{
    uint16_t voltage;
    char ID ;
    char TempByte;
    char RTCday[2];
    char RTCmonth[2];
    char RTCyear[2];
    char RTChour[2];
    char RTCmin[2];
    char Sepbyte;   
}dvar = { 500, 'X' , '>' , "18" , "10" , "15" , "20" , "15" , '#'};

I then convert it to a char array using the following:

char b[sizeof(struct foo)];
memcpy(b, &dvar, sizeof(struct foo));

However for some reason I get these trailing values in the char array

0x0A 0xFF

I initially thought it was getting the values because when i cast it to a char array it was effectively casting it to a string so I though the was the NULL '\0'

Any help will be appreciated.

Thanks

CSharper
  • 81
  • 7
  • 4
    I don't see where is structure `datadownload` and what is the size of it – Gopi Oct 20 '15 at 06:20
  • 1
    What do you mean by "trailing values"? How do you examine the contents of the array? And are you programming C or C++? The semantics could be different. On an unrelated note, have you though of using a union instead? – Some programmer dude Oct 20 '15 at 06:24
  • 2
    http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member – Lundin Oct 20 '15 at 06:26
  • 2
    If you convert this to a `char` array, nobody is going to add a NULL terminator for you. You need to do that yourself. – fuz Oct 20 '15 at 06:26
  • datadownload is the foo structure. I was renaming it but forgot to rename it in memcpy. I renamed it in the post. Thanks for pointing it out – CSharper Oct 20 '15 at 06:27
  • I'm evaluating it by sending it to serial port. I just pass that the char array and increments until it reaches the end of the array – CSharper Oct 20 '15 at 06:29
  • @Lundin I almost thought that padding was the issue but my struct has no padding or white spaces in it. – CSharper Oct 20 '15 at 06:33
  • 2
    Your `memcpy` is useless in the example, the cast happens with passing `&dvar` as the parameter of type `void *`. This would also work: `char *b = &dvar;` or better `char *b = (char *)&dvar;` – Melebius Oct 20 '15 at 06:35
  • @Lundin I also set the exact size of the struct myself without using sizeof and I still get the same issue – CSharper Oct 20 '15 at 06:37
  • @CSharper The bug is either related to struct padding or to missing null termination. At any rate, it is non-portable because of struct padding. – Lundin Oct 20 '15 at 06:40
  • Please just don't do this. If you need data in a particular byte format to send over a serial or network link, write proper code to serialize it into that format. Don't use things like `memcpy` on integers or `sizeof` on structures that depend on details of the implementation. – David Schwartz Oct 20 '15 at 22:02

2 Answers2

4

On modern processors, sizeof(struct data download) needs to be aligned on 32bits boundaries. Your data structure size is 8 chars + 1 short (16 bits) integer. The compiler needs to add 2 chars to the size of the structure to be able to handle it correctly when assigning it. Since you're doing communication over a serial line and know exactly what you're sending, you might as well specify the exact number of bytes you're willing to send over your serial lines: 2 +/*1 short */ + 8 (8 bytes).

ThBB
  • 66
  • 2
1

I have a sneaky suspicion you are using an 8bit microcontroller! You can debug by printing b[sizeof(foo)], and b[sizeof(foo)+1] These will be your two characters. If you noticed, you should not be referencing these, they are outside the bounds of your char array. eg n element array [0..(n-1)] (copied from your struct)

If you add an unused element to your struct(or increase the size of your final member) the char array can be terminated '\0' -compiler probably wants to do this.

Or do a pointer assignment as @Melebius has shown.