EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

alignment

Started by from...@... July 15, 2005
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



Beginning Microcontrollers with the MSP430

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

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


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


The 2024 Embedded Online Conference