PDA

View Full Version : [SOLVED] quint16 weirdness



pdoria
14th October 2009, 20:55
Or it's me who's finally gone bananas! :D

I have this piece of (testing) code:



#include <iostream>
#include <stdio.h>

#include <QCoreApplication>

int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);

unsigned int i;

typedef struct
{
quint16 response_id;
quint32 status_change_id;
bool result_code; // true if sucessful, false otherwise
quint8 reserved[3]; /* Set to 0 */
} receipt_data_type;


receipt_data_type *receipt = new receipt_data_type;
receipt->response_id = 0x0812;
receipt->status_change_id = 1;
receipt->result_code = true;
receipt->reserved[0] = 0;
receipt->reserved[1] = 0;
receipt->reserved[2] = 0;


char * p = (char *) receipt;
for (i=0; i < sizeof(receipt_data_type); i++) {
printf("%02X\r\n", *p++);
}
printf("\r\nAll members of receipt (total size:%d ) \r\n", sizeof(receipt_data_type) );
printf("response_id: %02X (size: %d )\r\n",receipt->response_id, sizeof(receipt->response_id) );
printf("status_change_id: %02X (size: %d )\r\n",receipt->status_change_id, sizeof(receipt->status_change_id));
printf("result_code: %02X (size: %d )\r\n",receipt->result_code, sizeof(receipt->result_code));
printf("reserved[0]: %02X\r\n",receipt->reserved[0]);
printf("reserved[1]: %02X\r\n",receipt->reserved[1]);
printf("reserved[2]: %02X\r\n",receipt->reserved[2]);

delete receipt;

return 0;
}


Expected results:
sizeof(receipt_data_type) == 10

Actual results:
sizeof(receipt_data_type) == 12

and what's the actual ouput:
12
08
FFFFFFCD
09 these two bold bytes shouldn't be here!
01
00
00
00
01
00
00
00

All members of receipt (total size:12 )
response_id: 812 (size: 2 )
status_change_id: 01 (size: 4 )
result_code: 01 (size: 1 )
reserved[0]: 00
reserved[1]: 00
reserved[2]: 00


Now the weird thing is that if I take out the response_id from the structure it reports the correct size (8).

What in the name of God am I missing?! :confused:

Thanks in advance,
Pedro Doria Meunier.

caduel
14th October 2009, 21:03
you are missing: alignment.
the compiler aligns the 4 byte integer to an adress divisible by 4. (efficiency reasons mainly; though there are (or have been) cpus that can only access an integer if it is located at such an adresss)

pdoria
14th October 2009, 21:10
Caduel... MANY MANY THANKS!

I was going bananas with this one! :D

In the end, per your advice, I solved it with:



#pragma pack(push)
#pragma pack(1)

faldzip
14th October 2009, 22:42
As I see you are trying to send your struct as a packet trough network. I would recommend way that needs more lines of code (and more work) but I guess it is safer. Because you forgot about endianess. Qt is cross platform so it can run on many platforms and on some of them endianess could be different. I would add method like toByteArray() to your struct which will return QByteArray containing you package so you can send it through the network.
Unfortunately in this method you should change every struct member to set of bytes and put them in some order into QByteArray. Then on the other side you can have fromByteArray(QByteArray) method to convert back from QByteArray into your struct which will require making for example one integer from 4 bytes read from byte array.

pdoria
15th October 2009, 00:09
Thank you faldzip for your insight.

Really helpful! :)

Best regards,
Pedro Doria Meunier.