How paranoid do I have to be about word alignment when working in C on the '430? I think we had someone in here a while back who'd defined a struct with a 16-bit value starting an odd number of bytes in, and had got no warning from the compiler he was using. I assume I should just worry if I put (unsigned*) in front of something which was char*, and make sure it is an even value I'm casting.... I assume malloc and stuff will always give me space starting on an even byte boundary? can I rely on the compiler to always use byte-reads on char values and word-reads on >-bit values? I assume 32 and 64-bit values can start on any even-byte boundary.... mutter.... anywhere else I might not have thought of? David
alignment
Started by ●July 15, 2005
Reply by ●July 15, 20052005-07-15
David, > How paranoid do I have to be about word alignment when > working in C on the '430? Depends. Eith the exclusion of casting and unions, you don't need to be concerned. > I think we had someone in here a while back who'd defined a > struct with a 16-bit value starting an odd number of bytes > in, and had got no warning from the compiler he was using. It would be difficult to ask the compiler to place a 16-bit data item on a mis-aligned address. Certinaly you can't do it for ours. > I assume I should just worry if I put (unsigned*) in front of > something which was char*, and make sure it is an even value > I'm casting.... If you convert a char * to unsigned *, I believe the bottom bit of the address is ignored by the MSP, but in practice you can't rely on that. > I assume malloc and stuff will always give me space starting > on an even byte boundary? malloc and friends always return you a pointer that will be correctly aligned for the largest aligned data item that the C compiler supports. For instance, if double require an alignment of 8, then malloc will always return you something that's a multiple of 8. > can I rely on the compiler to always use byte-reads on char > values and word-reads on >-bit values? I assume 32 and > 64-bit values can start on any even-byte boundary.... mutter.... 32-bit and 64-bit values will generally be composed of 16-bit data on a 16-bit processor, hence they have an alignment of 2 and will (almost) always use word reads and writes, except where the compiler can be "clever". As to forgetting anything, the only other thing to worry about is byte order. -- Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk CrossWorks for MSP430, ARM, AVR and now MAXQ processors
Reply by ●July 18, 20052005-07-18
Thanks Paul... > > How paranoid do I have to be about word alignment when > > working in C on the '430? > > Depends. With the exclusion of casting and unions, you don't need to be > concerned. > > I think we had someone in here a while back who'd defined a > > struct with a 16-bit value starting an odd number of bytes > > in, and had got no warning from the compiler he was using. > > It would be difficult to ask the compiler to place a 16-bit data item on > a mis-aligned address. Certainly you can't do it for ours. OK, so you're saying that if I define struct{ char C ; unsigned U ; } then the storage layout will automatically be confined by your compiler to be: [ C byte ] [ n/u byte ] [ U word ] and I can rely on this and never think about it unless I try to define a union of the structure with something more grainy.. .... on the other hand if I DO rely on it and it ever goes through a less clever compiler..... > > I assume I should just worry if I put (unsigned*) in front of > > something which was char*, and make sure it is an even value > > I'm casting.... > > If you convert a char * to unsigned *, I believe the bottom bit of the > address is ignored by the MSP, but in practice you can't rely on that. well, yes, that's what the hardware manual says, but it isn't going to pick up exactly what I hoped/expected if I'm not thinking about it. > > I assume malloc and stuff will always give me space starting > > on an even byte boundary? > > malloc and friends always return you a pointer that will be correctly > aligned for the largest aligned data item that the C compiler supports. > For instance, if double require an alignment of 8, then malloc will > always return you something that's a multiple of 8. Wow... Given what you say about the fact that one only needs to align 4/8 bytes objects on a 2-byte boundary, isn't that rather wasteful? Ah, I see, you're saying that mallloc will align to the hardware requirement, so on an MSP430 that would only be on a 2-byte boundary, as 4/8 byte objects are not native, and don't need to be aligned... .. or what are you saying :-) ? > > can I rely on the compiler to always use byte-reads on char > > values and word-reads on >-bit values? I assume 32 and > > 64-bit values can start on any even-byte boundary.... mutter.... > > 32-bit and 64-bit values will generally be composed of 16-bit data on a > 16-bit processor, hence they have an alignment of 2 and will (almost) > always use word reads and writes, except where the compiler can be > "clever". well I assume being clever includes generating working code. my question is, I guess, what will the internal allocation for struct{ char C ; long long unsigned U64 ; } be: [ C byte ] [ n/u byte ] [ U64 quadword ] or [ C byte ] [ n/u 7 bytes ] [ U64 quadword ] > As to forgetting anything, the only other thing to worry about is byte > order. well I'm ex x-86 so I guess it should all come naturally... ... for instance a 32-bit unsigned will consist of 4 bytes, in ascending addresses, in ascending order of significance... David
Reply by ●July 18, 20052005-07-18
Hi David, [ snip ] > > It would be difficult to ask the compiler to place a 16-bit > data item > > on a mis-aligned address. Certainly you can't do it for ours. > > OK, so you're saying that if I define > > struct{ > char C ; > unsigned U ; > } > > then the storage layout will automatically be confined by > your compiler to > be: > > [ C byte ] > [ n/u byte ] > [ U word ] > > and I can rely on this and never think about it unless I try > to define a union of the structure with something more grainy.. Don't understand the "more grainy" reference; if you compile this with our AVR compiler, for instance, then this structure will be 3 bytes with no unused byte. Compiling with ARM makes it eight bytes with three unused bytes. > .... on the other hand if I DO rely on it and it ever goes > through a less clever compiler..... Cleverness is not an option. There are a few rules imposed by the C standard and the underlying architecture... > > > I assume I should just worry if I put (unsigned*) in front of > > > something which was char*, and make sure it is an even value I'm > > > casting.... > > > > If you convert a char * to unsigned *, I believe the bottom > bit of the > > address is ignored by the MSP, but in practice you can't > rely on that. > > well, yes, that's what the hardware manual says, but it isn't > going to pick up exactly what I hoped/expected if I'm not > thinking about it. Correct. This type of thing usually crops up in comms protocols and badly-written software that maps underlying packets directly onto a struct. Might work great on one architecture, but not another. > > > I assume malloc and stuff will always give me space > starting on an > > > even byte boundary? > > > > malloc and friends always return you a pointer that will be > correctly > > aligned for the largest aligned data item that the C > compiler supports. > > For instance, if double require an alignment of 8, then malloc will > > always return you something that's a multiple of 8. > > Wow... Given what you say about the fact that one only needs > to align 4/8 bytes objects on a 2-byte boundary, isn't that > rather wasteful? The ARM has a "double" alignment of 4, hence allocating 1 char will allocate at least four bytes of memory, possibly more depending upon memory management. Doing the same on an MSP with a "double" alignment of 2 will allocate at least two bytes of memory. Don't think about object sizes, think of alignment requirements. > Ah, I see, you're saying that mallloc will align to the > hardware requirement, so on an MSP430 that would only be on a > 2-byte boundary, as > 4/8 byte objects are not native, and don't need to be aligned... Correct. > .. or what are you saying :-) ? > > > > can I rely on the compiler to always use byte-reads on > char values > > > and word-reads on >-bit values? I assume 32 and 64-bit > values can > > > start on any even-byte boundary.... mutter.... > > > > 32-bit and 64-bit values will generally be composed of > 16-bit data on > > a 16-bit processor, hence they have an alignment of 2 and will > > (almost) always use word reads and writes, except where the > compiler > > can be "clever". > > well I assume being clever includes generating working code. > my question is, I guess, what will the internal allocation for > > struct{ > char C ; > long long unsigned U64 ; > } > > be: > > [ C byte ] > [ n/u byte ] > [ U64 quadword ] That's it for MSP. > or > > [ C byte ] > [ n/u 7 bytes ] > [ U64 quadword ] No, that won't happen for MSP. I don't think it happens for ARM either, there would be three unused bytes. -- Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk CrossWorks for MSP430, ARM, AVR and now MAXQ processors