Yahoo Groups archive

Lpc2000

Index last updated: 2026-04-28 23:31 UTC

Message

Re: For C Experts

2006-03-31 by garycordelli

Dave:

While what you said may sound reasonable to humans, it is demonstrably
not so certain in software. :-)

To be specific, what you have in your original example is *not* a
simple structure.  Your new example "sets up" the compiler to *know*
precisely what is going on, so -- if it is inclined to generate some
nice byte-swapping/byte-copying code -- it knows that it will have to
do so.

However, let's change your new example to something that would "look"
more like the conditions present in your original example:
    #pragma packed(4)
    struct eg {
        char x;
        int y;
        char z;
        int w;
    };

Now you have "properly aligned" ints, just as you did in your original
example (in the case of x[4], for example).  But, then you introduced
the casting operation.  Hmmm.  So, this would be, in effect, doing
something like:
    char buf[] = { 1, 2, 3, 4, 5, 6, 7, 8, ...};

    for (i = 0; i < 4; i++) {
        struct eg *p = (struct eg*)&buf[i];
        ...

Now, what happens when you try to read/write the p->y and p->w members
of this structure?

"It depends!"

See, the compiler is likely to think that -- because you properly
packed the structure -- it does not have to generate byte-copy kludges
to access these members.  They appear properly aligned to access using
LDR.  HOWEVER, what happens if the whole darn structure STARTS at an
odd address?  Well, that odd *external* alignment quite simply defeats
the whole benefit of the proper *internal* alignment, ruining the
best-laid plans of the compiler and you.  And, what exactly is it that
defines "bad" *external* alignment of the structure?  Is it when "i"
is not a multiple of 4?  NO.  NO?  NO.  It is when the ADDRESS OF
"buf[i]" is not a multiple of 4 -- and this depends not only on the
value of "i", but on the actual starting address of "buf"...something
that the compiler DOES NOT KNOW.  That depends on where the linker
puts it (or, if it were allocated dynamically, rather than as you show
it, it would depend on where the memory allocation routine found space
for it).

If you try out the above properly aligned structure definition with a
"cast" to a char buffer of unknown alignment, you will find that just
about every compiler will fail to produce the "right" code to work in
every circumstance, and that the use of "proper alignment" in the
structure definition will fool it into thinking there is no cause for
even so much as a warning to you.

This, I think, is the downfall of your original example.  You declared
some "auto" or static ints (x[4]), can't tell which from the code
excerpt.  The compiler knew enough to force their alignment on the
stack or in memory to an appropriate boundary to make them accessible
with a normal int-aligned addressing mode.  However, the compiler had
no reason to care a bit about the alignment of "char buf[]", since it
expects you to be using it to hold chars (silly compiler).  But, then
you threw the compiler a curve by using an int* to access an arbitrary
spot in a  byte-aligned buffer and assign this to one of those x[i]'s.
 What's a poor compiler to do?

You owe the compiler an apology.

cordeg


--- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@...> wrote:
>
> ints are not always word aligned. For example:
> 
> #pragma packed(1)
> struct eg
>      {
>      char x;
>      int y;
>      char z;
>      int w;
>      }test;
> 
> One of the integers in this structure is not word word aligned and yet
> reference to the non word aligned integer works fine, as should
> 
> int x, *ip;
> ip = &test.w;
> x = *ip;
> 
> 
> --- In lpc2000@yahoogroups.com, "fordp2002" <SimonEllwood@> wrote:
> >
> > By casting buf to an int you have instructed the compiler NOT to treat
> > it as a byte.
> > 
> > It is beholden on you the software engineer to ensure whatever you
> > cast is compatible with what you cast it too. In this case you are
> > saying that &buf[i] is word aligned, which will be only true for one
> > in four cases of i. If the compiler aligns the start of buf to a word
> > bondary which will happen under some cases &buf[0] will be the only
> > legal cast.
> > 
> > FordP
> > 
> > 
> > --- In lpc2000@yahoogroups.com, David Hawkins <dwh@> wrote:
> > >
> > > dsidlauskas1 wrote:
> > > > Consider the following code:
> > > > 
> > > > ============================
> > > > char buf[]={1,2,3,4,5,6,7,8};
> > > > int *ip, x[4];
> > > > 
> > > > for (i=0; i<4; i++)
> > > >     {
> > > >     ip = (int *)&buf[i];
> > > >     x[4]  = *ip;
> > > >     }
> > > 
> > > Er, given the fact that x is of length 4,
> > > the statement x[4] = *ip is actually out-of-bounds.
> > > 
> > > Dave
> > >
> >
>

Attachments

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.