This is really straight forward, but i am looking for a compact solution converting an arbitrary datatype to stray bytes, as stored in memory.
Is it true then, that the order of declaring fields in a structure are exactly the byte order in memory? Should I take a certain 'byte alignment' into account?
Any theory and example is welcome!
Martin
structure to bytes
-
- Active Member
- Posts: 32
- Joined: Thu Jun 03, 2010 12:16 pm
-
- Respected Member
- Posts: 318
- Joined: Tue Dec 15, 2009 12:46 am
The layout of a structures is determined by the ABI. See the Tools developer guide. Fields will be stored in memory in the same order as they are declared but there may be padding added between structure members to make each member aligned. For example:
Will be laid out as a 1 byte char followed by 3 bytes of padding followed by a 4 byte integer.
Code: Select all
struct s {
char c;
int x;
};
-
- Respected Member
- Posts: 377
- Joined: Thu Dec 10, 2009 6:07 pm
Just out of interest, reading this thread, how does...richard wrote:The layout of a structures is determined by the ABI. See the Tools developer guide. Fields will be stored in memory in the same order as they are declared but there may be padding added between structure members to make each member aligned. For example:
Will be laid out as a 1 byte char followed by 3 bytes of padding followed by a 4 byte integer.Code: Select all
struct s { char c; int x; };
Code: Select all
struct s {
char c;
int x;
char d;
int y;
char e;
int z;
char f;
};
Code: Select all
struct s {
char c;
char d;
char e;
char f;
int x;
int y;
int z;
};
-
- Respected Member
- Posts: 318
- Joined: Tue Dec 15, 2009 12:46 am
Yes, these will get laid out differently. The order of the fields is significant. The first example will have 3 bytes of padding after each char member and the second example will have no padding.
-
- Active Member
- Posts: 32
- Joined: Thu Jun 03, 2010 12:16 pm
Thanks for the advises! In the meantime I succeeded to convert my structure to bytes using reinterpretation:
But, is there a way back? Convert an array of bytes into a structure, int,.... etc.?
Normally in C, I would use: *( (int*) &framedata[0])
Code: Select all
void CopyToFrameData(unsigned char frameData[], int &datalength, AcqData data)
{
int size = sizeof(AcqData);
for (int i=0;i<size;i++)
{
frameData[i] = (data, char[])[i];
}
datalength = size;
}
Normally in C, I would use: *( (int*) &framedata[0])
-
- Respected Member
- Posts: 296
- Joined: Thu Dec 10, 2009 10:33 pm
In C the name of an array is a pointer to the first element of the array. So instead of "&framedata[0]" you only need "framedata".
I would be wary of casting pointers to byte arrays into pointers to integers and vice versa. Reason being that on different processor architectures the byte ordering of integers in memory is different. Big endian vs little endian. This may not matter in any one application on one processor type but if you ever want to run the code on a different machine, for testing purposes say, it may fail.
For similar reasons I would be wary of relying on the padding in structures. Some processors impose alignment restrictions. 16 bit words have to me on even addresses. 32 bit ints have to be 4 byte alingned etc. So just grabing a pointer into a structure and casting to what you think is there may not work on different architectures.
Better to ensure portability by explicitly shifting and masking things around to do the type conversions.
BUT if performance is really important you may have to use the simple casts. Macros that expand differently on little or big endian machines can help portability here.
I would be wary of casting pointers to byte arrays into pointers to integers and vice versa. Reason being that on different processor architectures the byte ordering of integers in memory is different. Big endian vs little endian. This may not matter in any one application on one processor type but if you ever want to run the code on a different machine, for testing purposes say, it may fail.
For similar reasons I would be wary of relying on the padding in structures. Some processors impose alignment restrictions. 16 bit words have to me on even addresses. 32 bit ints have to be 4 byte alingned etc. So just grabing a pointer into a structure and casting to what you think is there may not work on different architectures.
Better to ensure portability by explicitly shifting and masking things around to do the type conversions.
BUT if performance is really important you may have to use the simple casts. Macros that expand differently on little or big endian machines can help portability here.
-
- Active Member
- Posts: 32
- Joined: Thu Jun 03, 2010 12:16 pm
This reply is really fast! Thanks.
I was aware of the endians. Please say when I am wrong, but x86 and XMOS are both little endian processors aren't they?
For my project I have to decode binary frames from an UART into, at least int's. How would such a cast look like in XC?
I was aware of the endians. Please say when I am wrong, but x86 and XMOS are both little endian processors aren't they?
For my project I have to decode binary frames from an UART into, at least int's. How would such a cast look like in XC?