1

I'm still very new to C++ development, please keep this in mind during the scope of my questions. I have a legacy Delphi application which sends a message to my C++ window using SendMessage() with WM_COPYDATA. The application is using a record to transmit a blob of data:

TUser = record
    LastName:   String[28];
    FirstName:    String[28];
    ID:          String[20];
    DateOfBirth: String[10];
    Sex:         Boolean;
    Size:        Word;
    Weight:      Word;
  end;

In my C++ application, I have setup the following struct to read out the transmitted information:

typedef struct {
    char LastName[29];
    char FirstName[29];
    char ID[21];
    char DateOfBirth[11];
    bool Sex;
    unsigned short Size;
    unsigned short Weight;
} Legacy_TUser;

According to the Delphi documentation, a fixed String with e.g. the length of 40 will occupy 40 + 1 bytes. However, once I receive the data, I perform a size comparison of the received data and my struct setup:

Logger::Log("Size of data: %i", pcds->cbData);
Logger::Log("Size of struct: %i", sizeof(Legacy_TUser));

This results in an output of:

Size of data: 95
Size of struct: 96

Which brings me to my final question. I can't seem to find any reason why the size of my struct is one byte too large. The string length seems to be correct, the data which I read in is shifted by exactly one byte. What am I missing here?

JxV
  • 11
  • 1
  • 3
    There will be one byte of padding after `bool Sex` – M.M Feb 01 '17 at 09:13
  • http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member – M.M Feb 01 '17 at 09:13
  • Using structs as a blob is generally a bad idea because the language does not guarantee the layout of the struct. You can either use hacks to try and get a particular struct layout, or rewrite the code to not use this technique. – M.M Feb 01 '17 at 09:14
  • @M.M I cannot alter the legacy application, sadly. Therefore I will have to live with the struct option. – JxV Feb 01 '17 at 09:20
  • @M.M Your link seems to be the solution for my problem. If you wish to write up a quick answer post, I'll mark it as correct. – JxV Feb 01 '17 at 09:21
  • I've linked this question to that one, since you've indicated it answers your question – M.M Feb 01 '17 at 09:23
  • I presume my best guess is to read out each transmitted data member of the record manually from memory? – JxV Feb 01 '17 at 09:24
  • Yes. You can probably use whatever c++builder's version of `#pragma pack(1)` is too (the answers on the other thread discuss that option, probably C++B uses the same syntax as MSVC) – M.M Feb 01 '17 at 09:25
  • I don't think I'd do it the way you propose. I'd access the fields using pointer arithmetic. You know the offsets, it's just cleaner than trying to force the compiler to line up the types. And you need special processing for the char arrays anyway because they really aren't C strings. So putting them into C++ char arrays is asking for trouble. – David Heffernan Feb 01 '17 at 10:22
  • Yes, I did end up creating a custom routine that would read the memory address with offsets. It took me quite a while to figure out the first character was not actually part of the string, but a byte indicating the length. I got it working now, thanks for all your help! – JxV Feb 01 '17 at 15:03

0 Answers0