Yahoo Groups archive

Lpc2000

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

Thread

For C Experts

For C Experts

2006-03-30 by dsidlauskas1

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;
    }
=============================
The Keil compiler compiles this without warning, but does not produce
the expected (for me) result in x. The problem is that Keil uses the
LDR instruction to effect the transfer and this is valid only on 4
byte boundaries.

GCC compiles but does give a non-aligned access warning.

I believe that the compiler has enough information to use byte aligned
transfers, and should, or at least give a warning.

Anybody want to weigh in on this one.

Thanks in advance for your comments.

Dave Sidlauskas

Re: [lpc2000] For C Experts

2006-03-30 by Robert Bacs

I guess you used an out of bound index for array x :)

x[4] - array with four elements

So x[3] is the last element, and x[4] will be
overwrite 
the stack or some global data if the x array is
declared as global.

Regards,
Boby

--- dsidlauskas1 <dsidlauskas@...> 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;
>     }
> =============================
> The Keil compiler compiles this without warning, but
> does not produce
> the expected (for me) result in x. The problem is
> that Keil uses the
> LDR instruction to effect the transfer and this is
> valid only on 4
> byte boundaries.
> 
> GCC compiles but does give a non-aligned access
> warning.
> 
> I believe that the compiler has enough information
> to use byte aligned
> transfers, and should, or at least give a warning.
> 
> Anybody want to weigh in on this one.
> 
> Thanks in advance for your comments.
> 
> Dave Sidlauskas
> 
> 
> 
> 


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com

Re: For C Experts

2006-03-30 by brendanmurphy37

When you say "I believe that the compiler has enough information to 
use byte aligned transfers", are you refering to the line:

x[4] = *ip

If so, why do you expect byte transfers? You're copying from one 
integer sized object to another. What happened before this line is 
irrelevant (in particular the fact that you've forced the "ip" 
pointer to have a badly alligned value).

Or am I misunderstanding what you're asking?

Brendan

--- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@...> 
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;
>     }
> =============================
> The Keil compiler compiles this without warning, but does not 
produce
> the expected (for me) result in x. The problem is that Keil uses the
> LDR instruction to effect the transfer and this is valid only on 4
> byte boundaries.
> 
> GCC compiles but does give a non-aligned access warning.
> 
> I believe that the compiler has enough information to use byte 
aligned
Show quoted textHide quoted text
> transfers, and should, or at least give a warning.
> 
> Anybody want to weigh in on this one.
> 
> Thanks in advance for your comments.
> 
> Dave Sidlauskas
>

Re: [lpc2000] For C Experts

2006-03-30 by Robert Adsett

Quoting dsidlauskas1 <dsidlauskas@...>:

> 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;
>    }
> =============================
> The Keil compiler compiles this without warning, but does not produce
> the expected (for me) result in x. The problem is that Keil uses the
> LDR instruction to effect the transfer and this is valid only on 4
> byte boundaries.
>
> GCC compiles but does give a non-aligned access warning.
>
> I believe that the compiler has enough information to use byte aligned
> transfers, and should, or at least give a warning.
>
> Anybody want to weigh in on this one.

The short answer is that the code is broken.  The only semi-portable way to do
this is memcpy.

There is no requirement to provide a warning in this case AFAIK.  That's a
quality of implementation issue.

Robert

Re: [lpc2000] For C Experts

2006-03-30 by Sten

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;
>     }
> =============================
> The Keil compiler compiles this without warning, but does not produce
> the expected (for me) result in x. The problem is that Keil uses the
> LDR instruction to effect the transfer and this is valid only on 4
> byte boundaries.
> 
> GCC compiles but does give a non-aligned access warning.
> 
> I believe that the compiler has enough information to use byte aligned
> transfers, and should, or at least give a warning.
> 
> Anybody want to weigh in on this one.
> 
> Thanks in advance for your comments.
> 
> Dave Sidlauskas
> 

Hello Dave,

I'm not really sure what you expect from this piece of code, but I think your try to copy these 8
bytes in 4 half-word (16bit) operations in a loop. If yes you should increment your counter variable
i by 2 instead of 1.

I would suggest:
==================================================
char buf[]={1,2,3,4,5,6,7,8};
int *ip, x[4];		/* assuming that int is 16bit-wide on your compiler */

ip = (int*) buff;

for (i=0; i<4; i++) {
    x[i] = *ip++;		/* copy content with halfword-post-increment */
}
===================================================

-- 
/************************************************
 Do you need a tiny and efficient real time
 operating system (RTOS) with a preemtive
 multitasking for LPC2000 or AT91SAM7?

   http://nanortos.net-attack.de/

 Or some open-source tools and code for LPC2000?

   http://www.net-attack.de/

************************************************/

Re: For C Experts

2006-03-30 by brendanmurphy37

It's not at all clear what the actual intent of the programmer is for 
this: what's actually coded is a long way from memcpy, regardless of 
any assumptions you make about what the compiler does.

I'm actually a bit surprised that GCC gives a warning: the only 
really incorrect line (language-wise) is the "ip = (int *)&buf[i];" 
one, but the programmer here gives an explicit direction to the 
compiler (by using the explicit type cast) that they know what 
they're doing. Most compilers would I suspect not issue a warning in 
that circumstance.

All of which begs the question: what is the original intent?

Brendan

--- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> 
wrote:
>
> Quoting dsidlauskas1 <dsidlauskas@...>:
> 
> > 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;
> >    }
> > =============================
> > The Keil compiler compiles this without warning, but does not 
produce
> > the expected (for me) result in x. The problem is that Keil uses 
the
> > LDR instruction to effect the transfer and this is valid only on 4
> > byte boundaries.
> >
> > GCC compiles but does give a non-aligned access warning.
> >
> > I believe that the compiler has enough information to use byte 
aligned
> > transfers, and should, or at least give a warning.
> >
> > Anybody want to weigh in on this one.
> 
> The short answer is that the code is broken.  The only semi-
portable way to do
> this is memcpy.
> 
> There is no requirement to provide a warning in this case AFAIK.  
That's a
Show quoted textHide quoted text
> quality of implementation issue.
> 
> Robert
>

Re: [lpc2000] For C Experts

2006-03-30 by David Hawkins

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

Re: [lpc2000] Re: For C Experts

2006-03-30 by Geoffrey Wang

I believe he's saying that the compiler may/may not be intelligent enough to follow the logic and perform
byte-wise transfers.  I had the same issue with the Green Hills ARM toolset in trying to force a 
data abort for exception handling testing.  Of course, I've never seen this documented.

The GHS toolset used byte-wise transfers for

*((volatile int *) 0x00000001) = 0x12345678;

and had to obfuscate it to make a data abort

    volatile dword i;

   i = 1;
    *((unsigned int *) i) = 0x12345678;


Geoffrey
  When you say "I believe that the compiler has enough information to 
  use byte aligned transfers", are you refering to the line:

  x[4] = *ip

  If so, why do you expect byte transfers? You're copying from one 
  integer sized object to another. What happened before this line is 
  irrelevant (in particular the fact that you've forced the "ip" 
  pointer to have a badly alligned value).

  Or am I misunderstanding what you're asking?

  Brendan

  --- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@...> 
  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;
  >     }
  > =============================
  > The Keil compiler compiles this without warning, but does not 
  produce
  > the expected (for me) result in x. The problem is that Keil uses the
  > LDR instruction to effect the transfer and this is valid only on 4
  > byte boundaries.
  > 
  > GCC compiles but does give a non-aligned access warning.
  > 
  > I believe that the compiler has enough information to use byte 
  aligned
  > transfers, and should, or at least give a warning.
  > 
  > Anybody want to weigh in on this one.
  > 
  > Thanks in advance for your comments.
  > 
  > Dave Sidlauskas
  >






------------------------------------------------------------------------------
  YAHOO! GROUPS LINKS 

    a..  Visit your group "lpc2000" on the web.
      
    b..  To unsubscribe from this group, send an email to:
     lpc2000-unsubscribe@yahoogroups.com
      
    c..  Your use of Yahoo! Groups is subject to the Yahoo! Terms of Service. 


------------------------------------------------------------------------------



[Non-text portions of this message have been removed]

RE: [lpc2000] Re: For C Experts

2006-03-30 by Ed Koffeman

If your compiler has the __packed keyword then you could use:

__packed int *ip;

...

    ip = (__packed int *)&buf[i];

and the compiler should know to treat the alignment carefully.

But, it's inefficient.

Ed Koffeman

Re: [lpc2000] For C Experts

2006-03-30 by mfrazier@governors-america.com

The array x[4] has only four elements they are
        x[0]
        x[1]
        x[2]
        x[3]
attempting to write something to x[4] is not going into the array but 
writing outside of the array.

[Non-text portions of this message have been removed]

Re: [lpc2000] Re: For C Experts

2006-03-30 by K B Shah-lascaux

My 2 cents...

Many compiler have 
#pragma pack.... 
(I have seen this in Visual Studio ---  as well as in IAR compiler)
directive   Specially used with structures 

You may get issue with the  member of  a structure which is not alighed to BYTE ... specially while using simalr way of copying  data using pointers...

The pragma directive forces structure to pack ... the way to copy data will be always  to use memcpy i.e. byte  by byte copy ... it might be inefficient in case where you are looking for speed ..

I would like to say ewhen some one is using pointers and specially with type cast , person is well awre what he is doing.


K B 
Show quoted textHide quoted text
  ----- Original Message ----- 
  From: Ed Koffeman 
  To: lpc2000@yahoogroups.com 
  Sent: Thursday, March 30, 2006 12:07 PM
  Subject: RE: [lpc2000] Re: For C Experts





  If your compiler has the __packed keyword then you could use:

  __packed int *ip;

  ...

      ip = (__packed int *)&buf[i];

  and the compiler should know to treat the alignment carefully.

  But, it's inefficient.

  Ed Koffeman




------------------------------------------------------------------------------
  YAHOO! GROUPS LINKS 

    a..  Visit your group "lpc2000" on the web.
      
    b..  To unsubscribe from this group, send an email to:
     lpc2000-unsubscribe@yahoogroups.com
      
    c..  Your use of Yahoo! Groups is subject to the Yahoo! Terms of Service. 


------------------------------------------------------------------------------




------------------------------------------------------------------------------


  No virus found in this incoming message.
  Checked by AVG Free Edition.
  Version: 7.1.385 / Virus Database: 268.3.3/296 - Release Date: 29/03/2006


[Non-text portions of this message have been removed]

Re: For C Experts

2006-03-30 by fordp2002

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:
Show quoted textHide quoted text
>
> 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
>

Re: [lpc2000] Re: For C Experts

2006-03-30 by Robert Adsett

Quoting brendanmurphy37 <brendan.murphy@...>:

>
> It's not at all clear what the actual intent of the programmer is for
> this: what's actually coded is a long way from memcpy, regardless of
> any assumptions you make about what the compiler does.

Actually, I thought (still think) the intent is pretty obvious.  Take whatever
'starts' at buf[i] and put it into an int.  That can be implemented pretty
straightforwardly by a memcpy.  What do you see that memcpy wouldn't do?

> I'm actually a bit surprised that GCC gives a warning: the only
> really incorrect line (language-wise) is the "ip = (int *)&buf[i];"
> one, but the programmer here gives an explicit direction to the
> compiler (by using the explicit type cast) that they know what
> they're doing. Most compilers would I suspect not issue a warning in
> that circumstance.

I'm going to have to see what lint does when confronted with this.  I expect
it's going to be pretty verbose ;)

> All of which begs the question: what is the original intent?

Robert

Re: [lpc2000] For C Experts

2006-03-30 by Robert Adsett

Quoting David Hawkins <dwh@...>:

> 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.

Doh!  Also a problem.

LPC C Register Setup

2006-03-30 by George M. Gallant, Jr.

I would like at add code written in C (GCC) to an existing program
written 
in assembler. Currently, only register sp is setup. I notice registers
with names
a0, sl, fp in various crt0.s files. Is there a writeup available?

Thanks,
    George


[Non-text portions of this message have been removed]

Re: For C Experts

2006-03-30 by jayasooriah

Hello Dave,

I see two errors in the program that the KEIL compiler (justifiably
IMHO) does not pick up.

The first error, assignment #1 in for loop, explicitly tells the
compiler to cast to (int *) something that it will not understand as
(int *).  Thus the compiler thus has no say (IMHO) in questioning this
assignment, and which will no doubt cause of unaligned access errors
in the statement immediately after.

The second error, assignment #2 in the for loop, is the proverbial
array bounds problem that compilers tradionally shy away becuase of
the need for (potentially expensive) run-time support libraries to do
this properly.

Hope this helps.

Jaya

PS:  E&OE -- yahoo mail is not getting through and I have to resort to
web interface!

--- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@...> wrote:
Show quoted textHide quoted text
>
> 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;
>     }
> =============================
> The Keil compiler compiles this without warning, but does not produce
> the expected (for me) result in x. The problem is that Keil uses the
> LDR instruction to effect the transfer and this is valid only on 4
> byte boundaries.
> 
> GCC compiles but does give a non-aligned access warning.
> 
> I believe that the compiler has enough information to use byte aligned
> transfers, and should, or at least give a warning.
> 
> Anybody want to weigh in on this one.
> 
> Thanks in advance for your comments.
> 
> Dave Sidlauskas
>

Re: For C Experts

2006-03-30 by dsidlauskas1

Brendan,

The information to the compiler is in the line:

 ip = (int *)&buf[i];

Where it should be clear that the pointer is to an unaligned int.

Dave S.

--- In lpc2000@yahoogroups.com, "brendanmurphy37" <brendan.murphy@...>
wrote:
Show quoted textHide quoted text
>
> 
> When you say "I believe that the compiler has enough information to 
> use byte aligned transfers", are you refering to the line:
> 
> x[4] = *ip
> 
> If so, why do you expect byte transfers? You're copying from one 
> integer sized object to another. What happened before this line is 
> irrelevant (in particular the fact that you've forced the "ip" 
> pointer to have a badly alligned value).
> 
> Or am I misunderstanding what you're asking?
> 
> Brendan
> 
> --- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@> 
> 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;
> >     }
> > =============================
> > The Keil compiler compiles this without warning, but does not 
> produce
> > the expected (for me) result in x. The problem is that Keil uses the
> > LDR instruction to effect the transfer and this is valid only on 4
> > byte boundaries.
> > 
> > GCC compiles but does give a non-aligned access warning.
> > 
> > I believe that the compiler has enough information to use byte 
> aligned
> > transfers, and should, or at least give a warning.
> > 
> > Anybody want to weigh in on this one.
> > 
> > Thanks in advance for your comments.
> > 
> > Dave Sidlauskas
> >
>

Re: For C Experts

2006-03-30 by brendanmurphy37

Dave,

O.K. but your explicit type cast is effectively saying to the 
compiler "I know what I'm doing".

I don't have any good 'C' reference to hand, so I can't quote the 
formal way of expressing this, but an explicit type cast is a 
direction to the compiler to forget any original type information 
and treat it as the type of object specified. The fact that the 
original type meant that it could or even would be on an un-alligned 
address is I believe not relevant. 

Don't forget that in the line "ip = (int *)&buf[i];" all it's doing 
is giving the "ip" variable a value: no address is being de-
referenced. It's the next line that does the actual copy, which as I 
pointed out is copying an integer sized object from one place to 
another. It's on this line that any platform specific issues (such 
as unalligned accesses being disallowed or undefined) will show up, 
and yet there's no problem with the line itself. You're expecting 
the compiler to remember (at compile-time) that the pointer may have 
an invalid address in it: a pretty tall order (for the general case: 
it happens to be obvious enough to a human programmer here).

By the way, what exactly are you trying to do here: is it just to 
illustrate a point? Even if it did byte sized reads and writes, the 
code doesn't make much sense (even ignoring the out of bounds 
problem).

Brendan

--- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@...> 
wrote:
>
> Brendan,
> 
> The information to the compiler is in the line:
> 
>  ip = (int *)&buf[i];
> 
> Where it should be clear that the pointer is to an unaligned int.
> 
> Dave S.
> 
> --- In lpc2000@yahoogroups.com, "brendanmurphy37" <brendan.murphy@>
> wrote:
> >
> > 
> > When you say "I believe that the compiler has enough information 
to 
> > use byte aligned transfers", are you refering to the line:
> > 
> > x[4] = *ip
> > 
> > If so, why do you expect byte transfers? You're copying from one 
> > integer sized object to another. What happened before this line 
is 
> > irrelevant (in particular the fact that you've forced the "ip" 
> > pointer to have a badly alligned value).
> > 
> > Or am I misunderstanding what you're asking?
> > 
> > Brendan
> > 
> > --- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@> 
> > 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;
> > >     }
> > > =============================
> > > The Keil compiler compiles this without warning, but does not 
> > produce
> > > the expected (for me) result in x. The problem is that Keil 
uses the
> > > LDR instruction to effect the transfer and this is valid only 
on 4
Show quoted textHide quoted text
> > > byte boundaries.
> > > 
> > > GCC compiles but does give a non-aligned access warning.
> > > 
> > > I believe that the compiler has enough information to use byte 
> > aligned
> > > transfers, and should, or at least give a warning.
> > > 
> > > Anybody want to weigh in on this one.
> > > 
> > > Thanks in advance for your comments.
> > > 
> > > Dave Sidlauskas
> > >
> >
>

Re: For C Experts

2006-03-30 by jayasooriah

Dave,

To us the unaligned pointer assignment is obvious when we look at it
in context.

To the compiler, that line alone is not enough to say that assignment
is invalid.  For example, it is a perfectly valid if the value of "i"
is a multiple of four in your example.

Sometimes pointers are used to pass information which are not valid
pointers (but as an escape to the norm) and these pople would be
crossed if compilers did not allow them to do this.

Jaya

--- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@...> wrote:
Show quoted textHide quoted text
> The information to the compiler is in the line:
> 
>  ip = (int *)&buf[i];
> 
> Where it should be clear that the pointer is to an unaligned int.
> 
> Dave S.

Re: For C Experts

2006-03-30 by dsidlauskas1

OK. To the intent.

I've got a lot of code written for an 8 bit Z80 controller to port.
It does a lot of parsing of data out of communications buffers, thus
giving rise to the constructs of the type shown, i.e., figure out
where the object that you want is in the buffer, take that address and
cast it to a pointer of the proper type. The buffers always have byte
aligned data.

Now if you do something like;

#pragma pack(1)
struct my_buf {
      char buf[]={1,2,3,4,5,6,78};
      }b;

then if you replace buf with b.buf in the example it works fine.

Or many compilers have the keyword __packed. and if the interger
pointer is declared with:

__packed int *ip;

The example works fine. 

The problem when porting  is to find all of the places where this type
of declaration needs to be introduced. Often the problem will not show
itself because the buffer variable ends up being aligned. One slight
change to the memory map can bring about a problem totally
unrelated to the change.

I realize there's enough weasel room in the C99 spec to get the
compiler writers off the hook, but if their market is moving up from
the 8 to 32 biter's shouldn't they try harder?

Thanks for your comments.

Dave S.

--- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> wrote:
>
> Quoting brendanmurphy37 <brendan.murphy@...>:
> 
> >
> > It's not at all clear what the actual intent of the programmer is for
> > this: what's actually coded is a long way from memcpy, regardless of
> > any assumptions you make about what the compiler does.
> 
> Actually, I thought (still think) the intent is pretty obvious. 
Take whatever
> 'starts' at buf[i] and put it into an int.  That can be implemented
pretty
> straightforwardly by a memcpy.  What do you see that memcpy wouldn't do?
> 
> > I'm actually a bit surprised that GCC gives a warning: the only
> > really incorrect line (language-wise) is the "ip = (int *)&buf[i];"
> > one, but the programmer here gives an explicit direction to the
> > compiler (by using the explicit type cast) that they know what
> > they're doing. Most compilers would I suspect not issue a warning in
> > that circumstance.
> 
> I'm going to have to see what lint does when confronted with this. 
I expect
Show quoted textHide quoted text
> it's going to be pretty verbose ;)
> 
> > All of which begs the question: what is the original intent?
> 
> Robert
>

Re: For C Experts

2006-03-30 by dsidlauskas1

Ed, 

Yes, __packed works, but I'm porting a bunch of old 8 bit code that
doesn't have this sort of problems and its hard to find all of the
places where its needed.

Thanks,

Dave S.

--- In lpc2000@yahoogroups.com, "Ed Koffeman" <koffeman@...> wrote:
Show quoted textHide quoted text
>
> 
> 
> 
> If your compiler has the __packed keyword then you could use:
> 
> __packed int *ip;
> 
> ...
> 
>     ip = (__packed int *)&buf[i];
> 
> and the compiler should know to treat the alignment carefully.
> 
> But, it's inefficient.
> 
> Ed Koffeman
>

Re: For C Experts

2006-03-30 by dsidlauskas1

Whoops, too much MatLab lately. Make it x[10].

--- In lpc2000@yahoogroups.com, mfrazier@... wrote:
Show quoted textHide quoted text
>
> The array x[4] has only four elements they are
>         x[0]
>         x[1]
>         x[2]
>         x[3]
> attempting to write something to x[4] is not going into the array but 
> writing outside of the array.
> 
> [Non-text portions of this message have been removed]
>

Re: For C Experts

2006-03-30 by jayasooriah

Dave,

The satement "x[4] = ..." trashes memory where the the fifth element
of the array "x[]" would normally exist, because you have declared it
as "x[4]" which means it has only four elements.  Hence the array
bound problem.

Jaya

--- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@...> wrote:
Show quoted textHide quoted text
>
> I don't think its out of bound. X[4] is the 5th location in the
> buffer, &x[4] is it's address, and there are 4 bytes declared from
> theis address (5, 6, 7, 8).
> 
> Anyway, for the purpose of this example initialize the first 20
> locations of buf.
> 
> --- 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
> >
>

Re: For C Experts

2006-03-30 by dsidlauskas1

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:
Show quoted textHide quoted text
>
> 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@...m, 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
> >
>

Re: For C Experts

2006-03-30 by dsidlauskas1

Jaya,

Thanks. The x[4] was a blunder on my part when I wrote the message.
Make it x[10].

Your second point is the key issue. Why can't the compiler understand
that the cast (int *)&buf[i] is to a byte aligned type, since buf is
declared as char buf[x], and the default Keil compiler alignment for
char is byte? 

This sure isn't the way this code should be written, but I'm porting
old code so I have to deal with what I've got.

Thanks for your comments.

Dave S.
   

--- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote:
Show quoted textHide quoted text
>
> Hello Dave,
> 
> I see two errors in the program that the KEIL compiler (justifiably
> IMHO) does not pick up.
> 
> The first error, assignment #1 in for loop, explicitly tells the
> compiler to cast to (int *) something that it will not understand as
> (int *).  Thus the compiler thus has no say (IMHO) in questioning this
> assignment, and which will no doubt cause of unaligned access errors
> in the statement immediately after.
> 
> The second error, assignment #2 in the for loop, is the proverbial
> array bounds problem that compilers tradionally shy away becuase of
> the need for (potentially expensive) run-time support libraries to do
> this properly.
> 
> Hope this helps.
> 
> Jaya
> 
> PS:  E&OE -- yahoo mail is not getting through and I have to resort to
> web interface!
> 
> --- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@> 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;
> >     }
> > =============================
> > The Keil compiler compiles this without warning, but does not produce
> > the expected (for me) result in x. The problem is that Keil uses the
> > LDR instruction to effect the transfer and this is valid only on 4
> > byte boundaries.
> > 
> > GCC compiles but does give a non-aligned access warning.
> > 
> > I believe that the compiler has enough information to use byte aligned
> > transfers, and should, or at least give a warning.
> > 
> > Anybody want to weigh in on this one.
> > 
> > Thanks in advance for your comments.
> > 
> > Dave Sidlauskas
> >
>

Re: For C Experts

2006-03-31 by dsidlauskas1

Brendan,

You make a good case in your second paragraph.

The exampe I've presented is just a toy problem. The real case is
porting a lot of old Z80 code where such constructs work just fine
because everything is byte aligned. 

I would think that most compilers have implicit unaligned data types,
if for nothing else than to deal with byte packed structures.

In casting up from a byte aligned structure, why couldn't (shouldn't)
the compiler use it's byte aligned equivalent. 

For example, with Keil, the default cast to int from a byte aligned
type could (should) be __packed int.

If I cast

(int)buf;

where buf is a byte aligned type, then the compiler could treat it as

(__packed int)buf by default.

Thanks for your help.

Dave S.

--- In lpc2000@yahoogroups.com, "brendanmurphy37" <brendan.murphy@...>
wrote:
Show quoted textHide quoted text
>
> 
> Dave,
> 
> O.K. but your explicit type cast is effectively saying to the 
> compiler "I know what I'm doing".
> 
> I don't have any good 'C' reference to hand, so I can't quote the 
> formal way of expressing this, but an explicit type cast is a 
> direction to the compiler to forget any original type information 
> and treat it as the type of object specified. The fact that the 
> original type meant that it could or even would be on an un-alligned 
> address is I believe not relevant. 
> 
> Don't forget that in the line "ip = (int *)&buf[i];" all it's doing 
> is giving the "ip" variable a value: no address is being de-
> referenced. It's the next line that does the actual copy, which as I 
> pointed out is copying an integer sized object from one place to 
> another. It's on this line that any platform specific issues (such 
> as unalligned accesses being disallowed or undefined) will show up, 
> and yet there's no problem with the line itself. You're expecting 
> the compiler to remember (at compile-time) that the pointer may have 
> an invalid address in it: a pretty tall order (for the general case: 
> it happens to be obvious enough to a human programmer here).
> 
> By the way, what exactly are you trying to do here: is it just to 
> illustrate a point? Even if it did byte sized reads and writes, the 
> code doesn't make much sense (even ignoring the out of bounds 
> problem).
> 
> Brendan
> 
> --- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@> 
> wrote:
> >
> > Brendan,
> > 
> > The information to the compiler is in the line:
> > 
> >  ip = (int *)&buf[i];
> > 
> > Where it should be clear that the pointer is to an unaligned int.
> > 
> > Dave S.
> > 
> > --- In lpc2000@yahoogroups.com, "brendanmurphy37" <brendan.murphy@>
> > wrote:
> > >
> > > 
> > > When you say "I believe that the compiler has enough information 
> to 
> > > use byte aligned transfers", are you refering to the line:
> > > 
> > > x[4] = *ip
> > > 
> > > If so, why do you expect byte transfers? You're copying from one 
> > > integer sized object to another. What happened before this line 
> is 
> > > irrelevant (in particular the fact that you've forced the "ip" 
> > > pointer to have a badly alligned value).
> > > 
> > > Or am I misunderstanding what you're asking?
> > > 
> > > Brendan
> > > 
> > > --- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@> 
> > > 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;
> > > >     }
> > > > =============================
> > > > The Keil compiler compiles this without warning, but does not 
> > > produce
> > > > the expected (for me) result in x. The problem is that Keil 
> uses the
> > > > LDR instruction to effect the transfer and this is valid only 
> on 4
> > > > byte boundaries.
> > > > 
> > > > GCC compiles but does give a non-aligned access warning.
> > > > 
> > > > I believe that the compiler has enough information to use byte 
> > > aligned
> > > > transfers, and should, or at least give a warning.
> > > > 
> > > > Anybody want to weigh in on this one.
> > > > 
> > > > Thanks in advance for your comments.
> > > > 
> > > > Dave Sidlauskas
> > > >
> > >
> >
>

Re: For C Experts

2006-03-31 by dsidlauskas1

Jaya,

Since the compiler knows that buf is a byte aligned object, woutldn't
it be resonable for the compiler to treat

(int *)&buf[i]

as 

(__packed int *)&buf[i]

In general, if non-naturaly aligned objects are promoted by a cast,
shouldn't, by default, the cast be of the proper non-aligned type?

BTW. Really appreciate your discussion of interupts on your web site.

Dave


--- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote:
Show quoted textHide quoted text
>
> Dave,
> 
> To us the unaligned pointer assignment is obvious when we look at it
> in context.
> 
> To the compiler, that line alone is not enough to say that assignment
> is invalid.  For example, it is a perfectly valid if the value of "i"
> is a multiple of four in your example.
> 
> Sometimes pointers are used to pass information which are not valid
> pointers (but as an escape to the norm) and these pople would be
> crossed if compilers did not allow them to do this.
> 
> Jaya
> 
> --- In lpc2000@...m, "dsidlauskas1" <dsidlauskas@> wrote:
> 
> > The information to the compiler is in the line:
> > 
> >  ip = (int *)&buf[i];
> > 
> > Where it should be clear that the pointer is to an unaligned int.
> > 
> > Dave S.
>

Re: For C Experts

2006-03-31 by rtstofer

--- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@...> wrote:
>
> Jaya,
> 
> Since the compiler knows that buf is a byte aligned object, woutldn't
> it be resonable for the compiler to treat
> 
> (int *)&buf[i]
> 
> as 
> 
> (__packed int *)&buf[i]
> 
> In general, if non-naturaly aligned objects are promoted by a cast,
> shouldn't, by default, the cast be of the proper non-aligned type?
> 
> BTW. Really appreciate your discussion of interupts on your web site.
> 
> Dave
> 

I guess I don't see why the compiler should do anything.  You asked it
to cast the ADDRESS of a byte in memory to an int * which is an
address (by definition) and put it in another int * which is also an
address.  No problem...  So far everything is just an address.

Until you actually use the pointer to grab the contents of memory
there is no alignment issue.  And, on the i386 there still wouldn't be
a problem because the i386 doesn't care about alignment, just
endianness.  It is just a thing with the ARM (and others, I suppose)
that alignment is a concern.

As to porting: well, it is likely that nearly every line of C code is
suspect as almost everything is being done with pointers or structures
or is hardware specific.  Getting the program to work again will be
more of a challenge than simply rewriting it.  How big could it be if
it originally ran on an 8 bit processor?  Unless it is a full O/S like
CP/M and all of the utilities...

The best Fortran programs are written after you spill the box of
cards; rewriting the code may be faster and better.

Richard

Re: For C Experts

2006-03-31 by Guillermo Prandi

This is indeed a strange piece of code:

char buf[]={1,2,3,4,5,6,7,8};
int *ip, x[10];
for (i=0; i<4; i++)
{
ip = (int *)&buf[i];
x[4]  = *ip;
}

(I made x[10] as dsidlauskas1 said).

This code will repeatedly (and pointlessly) change the value of the 
memory addresses x+16 through x+19. The first time (if alignment and 
aliasing were non-issues) it would write 0x01020304 (or 0x04030201, 
depending on endianness); the second time it would write 0x02030405; 
the third time, 0x03040506; and the fourth and last time it would 
write 0x04050607.

I think that this piece of code is so confusing that I was lost in 
what it does or what it should do and became unsure about the span of 
the original question.

Anyway, regarding alignment problems: the packed attribute or pragma 
(depends on the compiler) may permit to treat some data with 
unaligned access. I am unsure if this extends to pointers. Consider 
the following declaration:

struct {
char x;
int y;
} st;

This implies unaligned access to st.y ONLY if a "packed" pragma or 
attribute was specified. If no "packed" attribute was used, then st.y 
would be exactly four bytes counting from &st (three bytes are lost 
after st.x). In GCC, you do this packing like this:

struct {
char x;
int y;
} st __attribute__((packed));

But I am not aware of any way of specifying such thing for an int 
pointer like this:

int* x __attribute__((packed)); /* this does not work */
/* gives warning: attribute packed ignored */

So I am not so convinced that "packed" is a solution. At least not 
without a previous investigation on each and every target compiler 
(you mentioned at least two: Keil and GCC... would them behave 
similarly on this?). You must be cautious about this.

The second thing to watch for is aliasing. Last week I was attempting 
something like this:

void func(int par);

int main(void)
{
float a = 1.0f;
func(*(int*)&a);
}

And then:
void func(int par)
{
float x;
x = *(float*)\u2225
...do something with x...
}

The reasons I was doing this are too long and shameful to explain 
here, but the point is that it didn't work at all. It worked nicely 
if I compiled with aliasing optimization off, but as soon as I used 
size or speed optimization, it became broken. First of all, I had to 
make some of the casting volatile, like this:

extern void func(int par);
float a = 1.0f;
func(*(volatile int*)&a);

If I didn't add the volatile modifier I sometimes didn't get "x" sent 
as the parameter "par", but some other value (usually the value that 
should have been sent in a previous call to func()). Next (and 
worst), I just had to replace the func() part by some inline 
assembling: there was no way I could get "x" (from func()) to get the 
correct value due to aliasing.

The point is: beware of these "it is not standard but it should work" 
type of constructs. They give you more headaches than you may 
anticipate. Perhaps an in-depth revision of your old Z-80 code would 
pay you better, no matter how long it is.

Guille

--- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote:
>
> Dave,
> 
> The satement "x[4] = ..." trashes memory where the the fifth element
> of the array "x[]" would normally exist, because you have declared 
it
Show quoted textHide quoted text
> as "x[4]" which means it has only four elements.  Hence the array
> bound problem.
> 
> Jaya
> 
> --- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@> wrote:
> >
> > I don't think its out of bound. X[4] is the 5th location in the
> > buffer, &x[4] is it's address, and there are 4 bytes declared from
> > theis address (5, 6, 7, 8).
> > 
> > Anyway, for the purpose of this example initialize the first 20
> > locations of buf.
> > 
> > --- 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
> > >
> >
>

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:
Show quoted textHide quoted text
>
> 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
> > >
> >
>

Re: For C Experts

2006-03-31 by jayasooriah

Dave,

I think what you are asking of the compiler is to connect the two
statements in the for() loop.  Compilers do not have this capability.
 Even if it did, it would have to also consider the for() statement
too, as your code would be legitimate if the for() statement was:

>  for (i = 0; i < ...; i += 4)

A purist would argue is that there is nothing wrong with the pointer
assignment given the explicit cast.  The error occurs only if (and
when) the pointer is dereferenced at runtime.

Making it a packed array on these grounds may not be what the
programmer intended.  Besides, packed array methods involve
implementation issues.

GCC was kind enough to allude you to the possibility of such an event
ocurring.  Note that it too did not make the relationship between the
two statements.  If it did, it would report an error, not a warning.

Jaya

--- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@...> wrote:
Show quoted textHide quoted text
>
> Jaya,
> 
> Since the compiler knows that buf is a byte aligned object, woutldn't
> it be resonable for the compiler to treat
> 
> (int *)&buf[i]
> 
> as 
> 
> (__packed int *)&buf[i]
> 
> In general, if non-naturaly aligned objects are promoted by a cast,
> shouldn't, by default, the cast be of the proper non-aligned type?
> 
> BTW. Really appreciate your discussion of interupts on your web site.
> 
> Dave

Re: For C Experts

2006-03-31 by dsidlauskas1

Richard,


"The best Fortran programs are written after you spill the box of
cards; rewriting the code may be faster and better."

Been there. Done that. Thanks for the chuckle.

Dave

--- In lpc2000@yahoogroups.com, "rtstofer" <rstofer@...> wrote:
Show quoted textHide quoted text
>
> --- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@> wrote:
> >
> > Jaya,
> > 
> > Since the compiler knows that buf is a byte aligned object, woutldn't
> > it be resonable for the compiler to treat
> > 
> > (int *)&buf[i]
> > 
> > as 
> > 
> > (__packed int *)&buf[i]
> > 
> > In general, if non-naturaly aligned objects are promoted by a cast,
> > shouldn't, by default, the cast be of the proper non-aligned type?
> > 
> > BTW. Really appreciate your discussion of interupts on your web site.
> > 
> > Dave
> > 
> 
> I guess I don't see why the compiler should do anything.  You asked it
> to cast the ADDRESS of a byte in memory to an int * which is an
> address (by definition) and put it in another int * which is also an
> address.  No problem...  So far everything is just an address.
> 
> Until you actually use the pointer to grab the contents of memory
> there is no alignment issue.  And, on the i386 there still wouldn't be
> a problem because the i386 doesn't care about alignment, just
> endianness.  It is just a thing with the ARM (and others, I suppose)
> that alignment is a concern.
> 
> As to porting: well, it is likely that nearly every line of C code is
> suspect as almost everything is being done with pointers or structures
> or is hardware specific.  Getting the program to work again will be
> more of a challenge than simply rewriting it.  How big could it be if
> it originally ran on an 8 bit processor?  Unless it is a full O/S like
> CP/M and all of the utilities...
> 
> The best Fortran programs are written after you spill the box of
> cards; rewriting the code may be faster and better.
> 
> Richard
>

Re: For C Experts

2006-03-31 by dsidlauskas1

Cordeg,

Thanks for taking the time to comment. You've presented a though case,
but I'm not going to let my compiler off so easily :-).

In your case I think the compiler should throw an error, although it
does know that buf is byte aligned and...

In my case I think the compiler should compile working code.

I won't repeat all of the reasons, which are spread through the thread.

Thanks again.

Dave

--- In lpc2000@yahoogroups.com, "garycordelli" <gary@...> wrote:
>
> 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
Show quoted textHide quoted text
> > > 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
> > > >
> > >
> >
>

Re: For C Experts

2006-03-31 by dsidlauskas1

Jaya,

I don't think I'm asking it to connect the two statements.

What I'm expecting it to do is to recognize that buf is a byte packed
object (the defalt for the compler)and when casting byte packed
objects the compiler should cast them to other byte packed objects.

in otherwords;

char buf[10];
int ip*;

ip = (int *)&buf[5];

should be treated by the compiler as:

ip = (__packed int *)&buf[5];

and this is because char buf[10] is a byte packed object for this
compiler.

Dave


--- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote:
Show quoted textHide quoted text
>
> Dave,
> 
> I think what you are asking of the compiler is to connect the two
> statements in the for() loop.  Compilers do not have this capability.
>  Even if it did, it would have to also consider the for() statement
> too, as your code would be legitimate if the for() statement was:
> 
> >  for (i = 0; i < ...; i += 4)
> 
> A purist would argue is that there is nothing wrong with the pointer
> assignment given the explicit cast.  The error occurs only if (and
> when) the pointer is dereferenced at runtime.
> 
> Making it a packed array on these grounds may not be what the
> programmer intended.  Besides, packed array methods involve
> implementation issues.
> 
> GCC was kind enough to allude you to the possibility of such an event
> ocurring.  Note that it too did not make the relationship between the
> two statements.  If it did, it would report an error, not a warning.
> 
> Jaya
> 
> --- In lpc2000@...m, "dsidlauskas1" <dsidlauskas@> wrote:
> >
> > Jaya,
> > 
> > Since the compiler knows that buf is a byte aligned object, woutldn't
> > it be resonable for the compiler to treat
> > 
> > (int *)&buf[i]
> > 
> > as 
> > 
> > (__packed int *)&buf[i]
> > 
> > In general, if non-naturaly aligned objects are promoted by a cast,
> > shouldn't, by default, the cast be of the proper non-aligned type?
> > 
> > BTW. Really appreciate your discussion of interupts on your web site.
> > 
> > Dave
>

Re: For C Experts

2006-03-31 by sonny945852001

Dave,

   x[4] = *ip;

I thought array index in C starts at zero so valid index for x is only
0,1,2,3 ?

Sonny

--- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@...> wrote:
Show quoted textHide quoted text
>
> 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;
>     }
> =============================
> The Keil compiler compiles this without warning, but does not produce
> the expected (for me) result in x. The problem is that Keil uses the
> LDR instruction to effect the transfer and this is valid only on 4
> byte boundaries.
> 
> GCC compiles but does give a non-aligned access warning.
> 
> I believe that the compiler has enough information to use byte aligned
> transfers, and should, or at least give a warning.
> 
> Anybody want to weigh in on this one.
> 
> Thanks in advance for your comments.
> 
> Dave Sidlauskas
>

Re: For C Experts

2006-03-31 by jayasooriah

Dave,

If I understand you (now more correctly): because byte packing is
default, you want a vanilla cast (without __packed prefix) to be
treated as byte packed cast.

How would a programmer then indicate a cast to a vanilla (not packed)
pointer?

If the compiler always assumes byte packed no matter what, arguably
the compiler cannot take advantage of the faster method of dealing
with composite objects.

Jaya

--- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@...> wrote:
Show quoted textHide quoted text
>
> Jaya,
> 
> I don't think I'm asking it to connect the two statements.
> 
> What I'm expecting it to do is to recognize that buf is a byte packed
> object (the defalt for the compler)and when casting byte packed
> objects the compiler should cast them to other byte packed objects.
> 
> in otherwords;
> 
> char buf[10];
> int ip*;
> 
> ip = (int *)&buf[5];
> 
> should be treated by the compiler as:
> 
> ip = (__packed int *)&buf[5];
> 
> and this is because char buf[10] is a byte packed object for this
> compiler.
> 
> Dave

Re: For C Experts

2006-03-31 by garycordelli

Dave,

Just a postscript: this is not an academic notion to which I allude,
but a common error in just the kind of code I am paid to fix every day.

The circumstances tend to be communications code, where the programmer
has created a generic n-byte buffer:
    unsigned char commbuf[SOME_SIZE];

and a few message structures:
    #pragma packed(4)
    typedef struct {
        int    msgtype;
        int    source;
        int    othercrap;
    } HEADER;
    typedef stuct {
        HEADER hdr;
        int    someparm;
        char   someotherparm;
        int    yetanotherparm;
    } MESSAGE_0;
    typedef struct {
        HEADER hdr;
        char   athing;
        char   another;
        int    athird;
    } MESSAGE_1;
    etc...

and then later in their code they accumulate a certain number of bytes
in that buffer (via RS-232, TCP, etc).  Now, let's say this is a
simple case where the first byte is a message type code.  So, the
programmer does something like (forget the poor form here, the point
is the alignment issue):

    switch (commbuf[0)
    {
        case 0:
            MESSAGE_0 *p = (MESSAGE_0*)commbuf;
            p->someparm = 8;
            ...

I can tell you that this code fails in just the way you describe on
almost every compiler.  The packing #pragma causes the compiler to be
complacent about accessing the ints within the MESSAGE_x structures. 
It PRESUMES that any time you statically/automatically allocate an
instance of the structure, say:
    MESSAGE_0 aCopyOfMessage0;

it will simply force an alignment equal to the internal alignment, so
that it can access the internal members most efficiently.

BUT, if you end-run the compiler by creating an instance of this
structure out of thin air by casting a structure pointer to a "char"
buffer, it has NO IDEA if that char buffer is aligned on an odd
address, a word address, or a dword address.  Just because its a
"char" buffer, does not mean it MUST be on an odd address.  It just
means it could be an ANY address.  And it is the *linker*, not the
compiler, that would know this, since the compiler had no reason to
give specific direction to the linker about its placement.

In situations like the above, the common fix is to force alignment of
the "char commbuf[]" buffer -- depending on the compiler, something like:
    #pragma alignment=4
    char commbuf[SOME_SIZE];

Then, the combination of the overall alignment and the internal
structure alignment will ensure that all MESSAGE_x types cast to the
contents of the buffer will be accessible using the
(aligned-presuming) code the compiler generated for accesses within
structures of those types.

You are not alone, of course, in wishing that compilers spent their
time analyzing your code to remove all potential error conditions, and
many do a darn good job of it as far as it goes.  But, the "cast"
operator in particular is a kind of "get out of jail free" card for
the compiler.  It says: "Don't bother me boy; I know what I'm doing!"

Even when you don't mean it :-)

Cordeg


--- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@...> wrote:
>
> Cordeg,
> 
> Thanks for taking the time to comment. You've presented a though case,
> but I'm not going to let my compiler off so easily :-).
> 
> In your case I think the compiler should throw an error, although it
> does know that buf is byte aligned and...
> 
> In my case I think the compiler should compile working code.
> 
> I won't repeat all of the reasons, which are spread through the thread.
> 
> Thanks again.
> 
> Dave
> 
> --- In lpc2000@yahoogroups.com, "garycordelli" <gary@> wrote:
> >
> > 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
Show quoted textHide quoted text
> > > > 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
> > > > >
> > > >
> > >
> >
>

Re: [lpc2000] Re: For C Experts

2006-03-31 by David Hawkins

Here's a another couple of comments to provide you some context
for this type of problem, i.e., of interpreting the contents
of a binary data stream;

"Machine independent binary formats"

Not binary executable, just binary numeric representations.
There's a few out there, but here's a couple;

XDR - external data representation; used by SUNRPC.

CDR - common data representation, used by CORBA

XDR and CDR define a machine independent set of rules for
data alignment, byte packing/padding, etc.

Example: When you need to send an object/struct to another
machine, you inject all the members into a CDR byte
stream, eg.

  struct test {
   char a;
   int b;
   float c;
   double d;
  };

  cdr << test.a;
  cdr << test.b;
  cdr << test.c;
  cdr << test.d;

and the CDR layer puts appropriate padding into the block
of bytes controlled by the CDR object. You then put an endian
flag, and length parameter on that block of bytes, and
send the block across the wire. The receiving machine
reads the endian flag, then the length, and then unpacks
the structure;

  cdr >> test.a;
  cdr >> test.b;

etc.

So, if you start out knowing you are going to communicate
between different machines, its best to select a machine
independent binary protocol and then use that.

You don't have to use the C++ versions of the tools.
For microcontrollers/DSPs, I use C structures that
adhere to the alignment requirements of CDR, and
then use ACE/C++ on the Linux control host.

Cheers
Dave

Re: [lpc2000] Re: For C Experts

2006-03-31 by Robert Adsett

At 11:49 PM 3/30/06 +0000, dsidlauskas1 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

Only if the compiler understands pragma packed(1) to mean byte alignment in 
the following structure.  Far from a sure thing. The compiler is quite 
allowed to insist that items be aligned on particular boundaries and for 
certain architectures to get decent performance they must.  Code that 
depends on the alignment is at the very least non-portable.  If you are 
porting from an 8 bit compiler as you indicated in another post then you 
also have to worry about sizes.  the size of that structure on an compiler 
in the most common 8 bit implementations would be 6 bytes.  On an ARM 
implementation it would be 16 bytes (6 of them would be padding).  If the 
compiler happened to understand the pragma it might bring it down to 10 bytes.

Robert

Re: [lpc2000] Re: For C Experts

2006-03-31 by Robert Adsett

At 11:35 PM 3/30/06 +0000, dsidlauskas1 wrote:
>OK. To the intent.

<snip>


>I realize there's enough weasel room in the C99 spec to get the
>compiler writers off the hook, but if their market is moving up from
>the 8 to 32 biter's shouldn't they try harder?

It's more than weasel room it's an intimate and integral part of the 
language and has been for over 20 years. IE it's a PRE-ANSI 
requirement.  All ANSI and ISO did was codify it.  The alignment 
requirements can be far stricter than what the ARM architecture imposes.

Robert

" 'Freedom' has no meaning of itself.  There are always restrictions,   be 
they legal, genetic, or physical.  If you don't believe me, try to chew a 
radio signal. "  -- Kelvin Throop, III
http://www.aeolusdevelopment.com/

Re: For C Experts

2006-03-31 by dsidlauskas1

Jaya,

The "vanilla" cast is only to be treated as a byte packed cast if the
object that is being cast is itself byte packed. 

In thinking about my original case, the compiler should at least warn
since, with;

char buf[]={...};
int *ip;

ip = (int *)&buf[i];

the left and right side of this assignment are not of the same type,
even though the declaration would have you think so. ip is a pointer
to a default word aligned object, and (int *)&buf[i] is a pointer to a   
byte aligned object. These are really not the same data types. 

But I'm afraid I may be getting ahead of myself here. If I'm not
careful someone is going to smack me with the C99 spec :-).

I'll stick with my original assertion that the compiler could deal
with this issue in a more useful way than it does.

Dave S.




--- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@...> wrote:
Show quoted textHide quoted text
>
> Dave,
> 
> If I understand you (now more correctly): because byte packing is
> default, you want a vanilla cast (without __packed prefix) to be
> treated as byte packed cast.
> 
> How would a programmer then indicate a cast to a vanilla (not packed)
> pointer?
> 
> If the compiler always assumes byte packed no matter what, arguably
> the compiler cannot take advantage of the faster method of dealing
> with composite objects.
> 
> Jaya
> 
> --- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@> wrote:
> >
> > Jaya,
> > 
> > I don't think I'm asking it to connect the two statements.
> > 
> > What I'm expecting it to do is to recognize that buf is a byte packed
> > object (the defalt for the compler)and when casting byte packed
> > objects the compiler should cast them to other byte packed objects.
> > 
> > in otherwords;
> > 
> > char buf[10];
> > int ip*;
> > 
> > ip = (int *)&buf[5];
> > 
> > should be treated by the compiler as:
> > 
> > ip = (__packed int *)&buf[5];
> > 
> > and this is because char buf[10] is a byte packed object for this
> > compiler.
> > 
> > Dave
>

Re: [lpc2000] For C Experts

2006-03-31 by Robert Adsett

At 03:26 PM 3/30/06 +0000, 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;
>     }
>=============================

As I said earlier I was curious as to what lint (in may case PC-Lint) would 
make of this. So I added the following to one of my files

void check( void)
{
char buf[]={1,2,3,4,5,6,7,8};
int *ip, x[4];
int i;

for (i=0; i<4; i++)
     {
     ip = (int *)&buf[i];
     x[4]  = *ip;
     }
}

Fixing up the missing declaration for i ;) And I got the following 
errors.  I would never actually let this get to the compiler until I had 
cleaned these up.

     ip = (int *)&buf[i];
e:\cygwin\home\radsett\newlib-lpc\_close_r.c  54  Note 927: cast from pointer
     to pointer

                |
     x[4]  = *ip;
e:\cygwin\home\radsett\newlib-lpc\_close_r.c  55  Warning 415: Likely access of
     out-of-bounds pointer (1 beyond end of data) by operator '[' [Reference:
     file e:\cygwin\home\radsett\newlib-lpc\_close_r.c: line 55]

e:\cygwin\home\radsett\newlib-lpc\_close_r.c  55  Info 831: Reference cited in
     prior message

|
}
e:\cygwin\home\radsett\newlib-lpc\_close_r.c  57  Warning 550: Symbol 'x' (line
     49) not accessed

e:\cygwin\home\radsett\newlib-lpc\_close_r.c  49  Info 830: Location cited in
     prior message

|
}
e:\cygwin\home\radsett\newlib-lpc\_close_r.c  57  Note 954: Pointer variable
     'ip' (line 49) could be declared as pointing to const

e:\cygwin\home\radsett\newlib-lpc\_close_r.c  49  Info 830: Location cited in
     prior message


/// Start of Pass 2 ///
                |
     x[4]  = *ip;
e:\cygwin\home\radsett\newlib-lpc\_close_r.c  55  Warning 415: Likely access of
     out-of-bounds pointer (1 beyond end of data) by operator '[' [Reference:
     file e:\cygwin\home\radsett\newlib-lpc\_close_r.c: line 55]
e:\cygwin\home\radsett\newlib-lpc\_close_r.c  55  Info 831: Reference cited in
     prior message
                |
     x[4]  = *ip;
e:\cygwin\home\radsett\newlib-lpc\_close_r.c  55  Warning 415: Likely access of
     out-of-bounds pointer (1 beyond end of data) by operator '[' [Reference:
     file e:\cygwin\home\radsett\newlib-lpc\_close_r.c: line 55]
e:\cygwin\home\radsett\newlib-lpc\_close_r.c  55  Info 831: Reference cited in
     prior message
                |
     x[4]  = *ip;
e:\cygwin\home\radsett\newlib-lpc\_close_r.c  55  Warning 415: Likely access of
     out-of-bounds pointer (1 beyond end of data) by operator '[' [Reference:
     file e:\cygwin\home\radsett\newlib-lpc\_close_r.c: line 55]
e:\cygwin\home\radsett\newlib-lpc\_close_r.c  55  Info 831: Reference cited in
     prior message
                |
     x[4]  = *ip;
e:\cygwin\home\radsett\newlib-lpc\_close_r.c  55  Warning 415: Likely access of
     out-of-bounds pointer (1 beyond end of data) by operator '[' [Reference:
     file e:\cygwin\home\radsett\newlib-lpc\_close_r.c: line 55]
e:\cygwin\home\radsett\newlib-lpc\_close_r.c  55  Info 831: Reference cited in
     prior message
                |
     x[4]  = *ip;
e:\cygwin\home\radsett\newlib-lpc\_close_r.c  55  Warning 415: Likely access of
     out-of-bounds pointer (1 beyond end of data) by operator '[' [Reference:
     file e:\cygwin\home\radsett\newlib-lpc\_close_r.c: line 55]
e:\cygwin\home\radsett\newlib-lpc\_close_r.c  55  Info 831: Reference cited in
     prior message

Kudos to GCC for picking up the alignment issue explicitly, Lint only hints 
at it with the pointer to pointer cast warning.

" 'Freedom' has no meaning of itself.  There are always restrictions,   be 
they legal, genetic, or physical.  If you don't believe me, try to chew a 
radio signal. "  -- Kelvin Throop, III
http://www.aeolusdevelopment.com/

Re: [lpc2000] Re: For C Experts

2006-03-31 by Robert Adsett

At 03:46 AM 3/31/06 +0000, dsidlauskas1 wrote:
>Jaya,
>
>The "vanilla" cast is only to be treated as a byte packed cast if the
>object that is being cast is itself byte packed.
>
>In thinking about my original case, the compiler should at least warn
>since, with;
>
>char buf[]={...};
>int *ip;
>
>ip = (int *)&buf[i];
>
>the left and right side of this assignment are not of the same type,
>even though the declaration would have you think so. ip is a pointer
>to a default word aligned object, and (int *)&buf[i] is a pointer to a
>byte aligned object. These are really not the same data types.

Sure they are the same type, you told the compiler they were the same 
type.  It went away assuming that you knew what you were talking 
about.  Silly compiler ;)

Robert

" 'Freedom' has no meaning of itself.  There are always restrictions,   be 
they legal, genetic, or physical.  If you don't believe me, try to chew a 
radio signal. "  -- Kelvin Throop, III
http://www.aeolusdevelopment.com/

Re: [lpc2000] Re: For C Experts

2006-03-31 by Robert Adsett

At 12:07 AM 3/31/06 +0000, dsidlauskas1 wrote:
>I would think that most compilers have implicit unaligned data types,
>if for nothing else than to deal with byte packed structures.

I used a number that don't.  Most notably the one for a CRAY XMP (64 bit 
alignment, except for character pointers)

Robert

" 'Freedom' has no meaning of itself.  There are always restrictions,   be 
they legal, genetic, or physical.  If you don't believe me, try to chew a 
radio signal. "  -- Kelvin Throop, III
http://www.aeolusdevelopment.com/

Re: [lpc2000] Re: For C Experts

2006-03-31 by Robert Adsett

At 06:34 PM 3/30/06 -0800, David Hawkins wrote:

>Here's a another couple of comments to provide you some context
>for this type of problem, i.e., of interpreting the contents
>of a binary data stream;
>
>"Machine independent binary formats"
>
>Not binary executable, just binary numeric representations.
>There's a few out there, but here's a couple;
>
>XDR - external data representation; used by SUNRPC.
>
>CDR - common data representation, used by CORBA
>
>XDR and CDR define a machine independent set of rules for
>data alignment, byte packing/padding, etc.

Another approach that makes a lot of sense its if this is going to/coming 
from a communications interface is to leave the structures alone (ie use 
the same declarations in both cases) and use a simple message cracking 
routine on input.  So rather than try to read an integer from an odd 
address use something like:

x = buf[i] + (buf[i+1] << CHAR_BIT);
sign_extend(x);

making sure buf is unsigned for what I hope are obvious reasons.  The sign 
extend is needed if the data coming from the channel is a 16 bit quantity 
and a is 32bits as would be the case if converting from an 8 bit processor 
to an ARM.  All the nastyness of dealing with sizes, signedness and 
endianness then ends up being confined to the one place as with the machine 
independent binary formats, it's just a little bit more explicit as suits 
the smaller micro.  It's no less efficient than forcing packed 
representations on the compiler at that point and the rest of the program 
can efficiently deal with the data in it's natural alignment.

Robert

" 'Freedom' has no meaning of itself.  There are always restrictions,   be 
they legal, genetic, or physical.  If you don't believe me, try to chew a 
radio signal. "  -- Kelvin Throop, III
http://www.aeolusdevelopment.com/

Re: For C Experts

2006-03-31 by jayasooriah

Hi Dave,

I see the problem you raise, but I am not sure if there is a clean
solution.

While all arrays may be packed, this does not mean that objects are
not on aligned in general.  The pointer to an integer you defined is
one such pointer that could be used to dereference aligned objects.

If the compiler were classify 'ip' as always referring to packed
array, this would be a disservice when it is used to dereference
aligned object.

It is worth pointing out that the C compiler characterises a variable
based on its deceleration and not its usage.

To incorporate your suggestion, it would also have to characterise the
 variable (in this case a pointer) based on its usage. I think this is
very hard to do, if at all possible.

The compiler would have told you this is wrong -- but you said "never
mind" by the explicit cast.  You think it should still warn you, but
another may retort "why do you think I made the explicit cast?"

At the risk of adding yet another dimension, I think the problem you
are alluding is very similar to subtle but potent distinction in C
between arrays and pointers.

Jaya

--- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@...> wrote:
>
> Jaya,
> 
> The "vanilla" cast is only to be treated as a byte packed cast if the
> object that is being cast is itself byte packed. 
> 
> In thinking about my original case, the compiler should at least warn
> since, with;
> 
> char buf[]={...};
> int *ip;
> 
> ip = (int *)&buf[i];
> 
> the left and right side of this assignment are not of the same type,
> even though the declaration would have you think so. ip is a pointer
> to a default word aligned object, and (int *)&buf[i] is a pointer to
a   
Show quoted textHide quoted text
> byte aligned object. These are really not the same data types. 
> 
> But I'm afraid I may be getting ahead of myself here. If I'm not
> careful someone is going to smack me with the C99 spec :-).
> 
> I'll stick with my original assertion that the compiler could deal
> with this issue in a more useful way than it does.
> 
> Dave S.

Re: For C Experts

2006-03-31 by brendanmurphy37

Dave,

Think about whet your saying here:

> ip = (int *)&buf[5];
> 
> should be treated by the compiler as:
> 
> ip = (__packed int *)&buf[5];
> 

"should" doesn't come into it! You have explicitley told the 
compiler exectly how you want it treated (the "(int *)"). Now if you 
had one of those magic "do what I mean, not what I say" compilers, 
you'd be fine......

By the way, if you find that compiler, let me know!

Brendan

--- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@...> 
wrote:
>
> Jaya,
> 
> I don't think I'm asking it to connect the two statements.
> 
> What I'm expecting it to do is to recognize that buf is a byte 
packed
> object (the defalt for the compler)and when casting byte packed
> objects the compiler should cast them to other byte packed objects.
> 
> in otherwords;
> 
> char buf[10];
> int ip*;
> 
> ip = (int *)&buf[5];
> 
> should be treated by the compiler as:
> 
> ip = (__packed int *)&buf[5];
> 
> and this is because char buf[10] is a byte packed object for this
> compiler.
> 
> Dave
> 
> 
> --- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@> wrote:
> >
> > Dave,
> > 
> > I think what you are asking of the compiler is to connect the two
> > statements in the for() loop.  Compilers do not have this 
capability.
> >  Even if it did, it would have to also consider the for() 
statement
> > too, as your code would be legitimate if the for() statement was:
> > 
> > >  for (i = 0; i < ...; i += 4)
> > 
> > A purist would argue is that there is nothing wrong with the 
pointer
> > assignment given the explicit cast.  The error occurs only if 
(and
> > when) the pointer is dereferenced at runtime.
> > 
> > Making it a packed array on these grounds may not be what the
> > programmer intended.  Besides, packed array methods involve
> > implementation issues.
> > 
> > GCC was kind enough to allude you to the possibility of such an 
event
> > ocurring.  Note that it too did not make the relationship 
between the
> > two statements.  If it did, it would report an error, not a 
warning.
> > 
> > Jaya
> > 
> > --- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@> 
wrote:
> > >
> > > Jaya,
> > > 
> > > Since the compiler knows that buf is a byte aligned object, 
woutldn't
> > > it be resonable for the compiler to treat
> > > 
> > > (int *)&buf[i]
> > > 
> > > as 
> > > 
> > > (__packed int *)&buf[i]
> > > 
> > > In general, if non-naturaly aligned objects are promoted by a 
cast,
> > > shouldn't, by default, the cast be of the proper non-aligned 
type?
> > > 
> > > BTW. Really appreciate your discussion of interupts on your 
web site.
Show quoted textHide quoted text
> > > 
> > > Dave
> >
>

Re: [lpc2000] Re: For C Experts

2006-03-31 by Sten

Hello,

Another solution I had last night which should fix the alignment-problem, because the union is
compiler will align this union to its biggest member:
===============================================================
union {
        char    u8[8];
        short   u16[4];
} buff = {1, 2, 3, 4, 5, 6, 7, 8};

int main(void) {
        short x[10], i;

        for (i = 0; i < 4; i++) {
                x[i] = buff.u16[i];
                printf(" %04x, ", x[i]);
        }

        return 0;
}
===============================================================

   Sten

brendanmurphy37 wrote:
> Dave,
> 
> Think about whet your saying here:
> 
> 
>>ip = (int *)&buf[5];
>>
>>should be treated by the compiler as:
>>
>>ip = (__packed int *)&buf[5];
>>
> 
> 
> "should" doesn't come into it! You have explicitley told the 
> compiler exectly how you want it treated (the "(int *)"). Now if you 
> had one of those magic "do what I mean, not what I say" compilers, 
> you'd be fine......
> 
> By the way, if you find that compiler, let me know!
> 
> Brendan
> 
> --- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@...> 
> wrote:
> 
>>Jaya,
>>
>>I don't think I'm asking it to connect the two statements.
>>
>>What I'm expecting it to do is to recognize that buf is a byte 
> 
> packed
> 
>>object (the defalt for the compler)and when casting byte packed
>>objects the compiler should cast them to other byte packed objects.
>>
>>in otherwords;
>>
>>char buf[10];
>>int ip*;
>>
>>ip = (int *)&buf[5];
>>
>>should be treated by the compiler as:
>>
>>ip = (__packed int *)&buf[5];
>>
>>and this is because char buf[10] is a byte packed object for this
>>compiler.
>>
>>Dave
>>
>>
>>--- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@> wrote:
>>
>>>Dave,
>>>
>>>I think what you are asking of the compiler is to connect the two
>>>statements in the for() loop.  Compilers do not have this 
> 
> capability.
> 
>>> Even if it did, it would have to also consider the for() 
> 
> statement
> 
>>>too, as your code would be legitimate if the for() statement was:
>>>
>>>
>>>> for (i = 0; i < ...; i += 4)
>>>
>>>A purist would argue is that there is nothing wrong with the 
> 
> pointer
> 
>>>assignment given the explicit cast.  The error occurs only if 
> 
> (and
> 
>>>when) the pointer is dereferenced at runtime.
>>>
>>>Making it a packed array on these grounds may not be what the
>>>programmer intended.  Besides, packed array methods involve
>>>implementation issues.
>>>
>>>GCC was kind enough to allude you to the possibility of such an 
> 
> event
> 
>>>ocurring.  Note that it too did not make the relationship 
> 
> between the
> 
>>>two statements.  If it did, it would report an error, not a 
> 
> warning.
> 
>>>Jaya
>>>
>>>--- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@> 
> 
> wrote:
> 
>>>>Jaya,
>>>>
>>>>Since the compiler knows that buf is a byte aligned object, 
> 
> woutldn't
> 
>>>>it be resonable for the compiler to treat
>>>>
>>>>(int *)&buf[i]
>>>>
>>>>as 
>>>>
>>>>(__packed int *)&buf[i]
>>>>
>>>>In general, if non-naturaly aligned objects are promoted by a 
> 
> cast,
> 
>>>>shouldn't, by default, the cast be of the proper non-aligned 
> 
> type?
> 
>>>>BTW. Really appreciate your discussion of interupts on your 
> 
> web site.
> 
>>>>Dave
>>>
> 
> 
> 
> 
> 
> 
>  
> Yahoo! Groups Links
> 
> 
> 
>  
> 
> 
> 


-- 
/************************************************
 Do you need a tiny and efficient real time
 operating system (RTOS) with a preemtive
 multitasking for LPC2000 or AT91SAM7?

   http://nanortos.net-attack.de/

 Or some open-source tools and code for LPC2000?

   http://www.net-attack.de/

************************************************/

Re: For C Experts

2006-03-31 by brendanmurphy37

Dave,

Sorry to be blunt, but you are incorrect when you state the left and 
right are not the same types. This might explain  why you think the 
compiler is in error.

> int *ip;
> 
> ip = (int *)&buf[i];
>

1. LHS: "ip" is declared as "int *"
2. RHS: regardless of what &buf[i] is declared as, you have forced 
the compiler to treat it as "int *" : that's what an explicit type 
cast does.

In other words, the RHS is exactly the same as the LHS. Hence no 
warning. 

I sympathise with your dilema in how to move from an existing (non-
portable) code base.

My suggestion would be to re-code the offending constructs: you're 
going to have to go through your code line-by-line in any case. You 
may as well fix it as you go. My strong recommendation would be not 
to use "packed" or any other such modifier: it's inherently non-
portable. You might get it to work for now, but what happens when 
you next move compiler or target?

The safest (i.e. portable) and simplest way of pulling bytes out of 
a buffer of bytes like this is to do it a byte at a time. As someone 
else has pointed out, this issue is very common in comms protocol 
software. Unfortunately there exist many, many examples of code that 
are inherently non-portable, which people have a habit of following.

Brendan


--- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@...> 
wrote:
>
> Jaya,
> 
> The "vanilla" cast is only to be treated as a byte packed cast if 
the
> object that is being cast is itself byte packed. 
> 
> In thinking about my original case, the compiler should at least 
warn
> since, with;
> 
> char buf[]={...};
> int *ip;
> 
> ip = (int *)&buf[i];
> 
> the left and right side of this assignment are not of the same 
type,
> even though the declaration would have you think so. ip is a 
pointer
> to a default word aligned object, and (int *)&buf[i] is a pointer 
to a   
> byte aligned object. These are really not the same data types. 
> 
> But I'm afraid I may be getting ahead of myself here. If I'm not
> careful someone is going to smack me with the C99 spec :-).
> 
> I'll stick with my original assertion that the compiler could deal
> with this issue in a more useful way than it does.
> 
> Dave S.
> 
> 
> 
> 
> --- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@> wrote:
> >
> > Dave,
> > 
> > If I understand you (now more correctly): because byte packing is
> > default, you want a vanilla cast (without __packed prefix) to be
> > treated as byte packed cast.
> > 
> > How would a programmer then indicate a cast to a vanilla (not 
packed)
> > pointer?
> > 
> > If the compiler always assumes byte packed no matter what, 
arguably
> > the compiler cannot take advantage of the faster method of 
dealing
> > with composite objects.
> > 
> > Jaya
> > 
> > --- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@> 
wrote:
> > >
> > > Jaya,
> > > 
> > > I don't think I'm asking it to connect the two statements.
> > > 
> > > What I'm expecting it to do is to recognize that buf is a byte 
packed
> > > object (the defalt for the compler)and when casting byte packed
> > > objects the compiler should cast them to other byte packed 
objects.
> > > 
> > > in otherwords;
> > > 
> > > char buf[10];
> > > int ip*;
> > > 
> > > ip = (int *)&buf[5];
> > > 
> > > should be treated by the compiler as:
> > > 
> > > ip = (__packed int *)&buf[5];
> > > 
> > > and this is because char buf[10] is a byte packed object for 
this
Show quoted textHide quoted text
> > > compiler.
> > > 
> > > Dave
> >
>

Re: For C Experts

2006-03-31 by brendanmurphy37

This is also non-portable.

Brendan

--- In lpc2000@yahoogroups.com, Sten <list@...> wrote:
>
> Hello,
> 
> Another solution I had last night which should fix the alignment-
problem, because the union is
> compiler will align this union to its biggest member:
> ===============================================================
> union {
>         char    u8[8];
>         short   u16[4];
> } buff = {1, 2, 3, 4, 5, 6, 7, 8};
> 
> int main(void) {
>         short x[10], i;
> 
>         for (i = 0; i < 4; i++) {
>                 x[i] = buff.u16[i];
>                 printf(" %04x, ", x[i]);
>         }
> 
>         return 0;
> }
> ===============================================================
> 
>    Sten
> 
> brendanmurphy37 wrote:
> > Dave,
> > 
> > Think about whet your saying here:
> > 
> > 
> >>ip = (int *)&buf[5];
> >>
> >>should be treated by the compiler as:
> >>
> >>ip = (__packed int *)&buf[5];
> >>
> > 
> > 
> > "should" doesn't come into it! You have explicitley told the 
> > compiler exectly how you want it treated (the "(int *)"). Now if 
you 
> > had one of those magic "do what I mean, not what I say" 
compilers, 
> > you'd be fine......
> > 
> > By the way, if you find that compiler, let me know!
> > 
> > Brendan
> > 
> > --- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@> 
> > wrote:
> > 
> >>Jaya,
> >>
> >>I don't think I'm asking it to connect the two statements.
> >>
> >>What I'm expecting it to do is to recognize that buf is a byte 
> > 
> > packed
> > 
> >>object (the defalt for the compler)and when casting byte packed
> >>objects the compiler should cast them to other byte packed 
objects.
> >>
> >>in otherwords;
> >>
> >>char buf[10];
> >>int ip*;
> >>
> >>ip = (int *)&buf[5];
> >>
> >>should be treated by the compiler as:
> >>
> >>ip = (__packed int *)&buf[5];
> >>
> >>and this is because char buf[10] is a byte packed object for this
> >>compiler.
> >>
> >>Dave
> >>
> >>
> >>--- In lpc2000@yahoogroups.com, "jayasooriah" <jayasooriah@> 
wrote:
> >>
> >>>Dave,
> >>>
> >>>I think what you are asking of the compiler is to connect the 
two
> >>>statements in the for() loop.  Compilers do not have this 
> > 
> > capability.
> > 
> >>> Even if it did, it would have to also consider the for() 
> > 
> > statement
> > 
> >>>too, as your code would be legitimate if the for() statement 
was:
Show quoted textHide quoted text
> >>>
> >>>
> >>>> for (i = 0; i < ...; i += 4)
> >>>
> >>>A purist would argue is that there is nothing wrong with the 
> > 
> > pointer
> > 
> >>>assignment given the explicit cast.  The error occurs only if 
> > 
> > (and
> > 
> >>>when) the pointer is dereferenced at runtime.
> >>>
> >>>Making it a packed array on these grounds may not be what the
> >>>programmer intended.  Besides, packed array methods involve
> >>>implementation issues.
> >>>
> >>>GCC was kind enough to allude you to the possibility of such an 
> > 
> > event
> > 
> >>>ocurring.  Note that it too did not make the relationship 
> > 
> > between the
> > 
> >>>two statements.  If it did, it would report an error, not a 
> > 
> > warning.
> > 
> >>>Jaya
> >>>
> >>>--- In lpc2000@yahoogroups.com, "dsidlauskas1" <dsidlauskas@> 
> > 
> > wrote:
> > 
> >>>>Jaya,
> >>>>
> >>>>Since the compiler knows that buf is a byte aligned object, 
> > 
> > woutldn't
> > 
> >>>>it be resonable for the compiler to treat
> >>>>
> >>>>(int *)&buf[i]
> >>>>
> >>>>as 
> >>>>
> >>>>(__packed int *)&buf[i]
> >>>>
> >>>>In general, if non-naturaly aligned objects are promoted by a 
> > 
> > cast,
> > 
> >>>>shouldn't, by default, the cast be of the proper non-aligned 
> > 
> > type?
> > 
> >>>>BTW. Really appreciate your discussion of interupts on your 
> > 
> > web site.
> > 
> >>>>Dave
> >>>
> > 
> > 
> > 
> > 
> > 
> > 
> >  
> > Yahoo! Groups Links
> > 
> > 
> > 
> >  
> > 
> > 
> > 
> 
> 
> -- 
> /************************************************
>  Do you need a tiny and efficient real time
>  operating system (RTOS) with a preemtive
>  multitasking for LPC2000 or AT91SAM7?
> 
>    http://nanortos.net-attack.de/
> 
>  Or some open-source tools and code for LPC2000?
> 
>    http://www.net-attack.de/
> 
> ************************************************/
>

RE: [lpc2000] Re: For C Experts

2006-03-31 by Paul Curtis

Hi, 

> I realize there's enough weasel room in the C99 spec to get 
> the compiler writers off the hook, but if their market is 
> moving up from the 8 to 32 biter's shouldn't they try harder?

C90 has been a standard for 16 years which is more than long enough for
engineering firms to understand that if they want to move up to 32 bits
then they need to start paying attention to the way they write code.

--
Paul Curtis, Rowley Associates Ltd   http://www.rowley.co.uk 
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

RE: [lpc2000] Re: For C Experts

2006-03-31 by Paul Curtis

Hi, 

> The exampe I've presented is just a toy problem. The real 
> case is porting a lot of old Z80 code where such constructs 
> work just fine because everything is byte aligned. 

Are you just lucky, too, that the byte order of multi-byte items works?
;-)  If you were porting from, say, a 68HC11 then you'd be royally
screwed with byte order and packing problems.

--
Paul Curtis, Rowley Associates Ltd   http://www.rowley.co.uk 
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

RE: [lpc2000] Re: For C Experts

2006-03-31 by Paul Curtis

Hi, 

> Since the compiler knows that buf is a byte aligned object, 
> woutldn't it be resonable for the compiler to treat
> 
> (int *)&buf[i]
> 
> as 
> 
> (__packed int *)&buf[i]
> 
> In general, if non-naturaly aligned objects are promoted by a 
> cast, shouldn't, by default, the cast be of the proper 
> non-aligned type?

Bloody hell no.  Insanity.

--
Paul Curtis, Rowley Associates Ltd   http://www.rowley.co.uk 
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

Re: For C Experts

2006-03-31 by Thiadmer Riemersma (ITB CompuPhase)

This is what "The C Programming Language" 2nd edition (Kernighan &
Ritchie) says (page 199):

"A pointer to one type may be converted to a pointer to another type.
The resulting pointer may cause addressing exceptions if the subject
pointer does not refer to an object suitably aligned in storage."

When casting pointers to another type, the programmer must keep an eye
on alignment. A compiler may use clever techniques to warn for
possible misalignment, but it is not required to do so.

Regarding the effort of examining all source code for type casts with
alignment problems, my opinion is that type casts should be used
sparingly. The requirement to "silence" the compiler with a type cast
already means that the compiler frowned upon the statement.

Thiadmer

Re: [lpc2000] Re: For C novices

2006-03-31 by Clyde Stubbs

On Fri, Mar 31, 2006 at 02:20:12AM -0000, garycordelli wrote:
> Just a postscript: this is not an academic notion to which I allude,
> but a common error in just the kind of code I am paid to fix every day.
> 
> The circumstances tend to be communications code, where the programmer
> has created a generic n-byte buffer:

Indeed. I'd love to have a dollar for every time someone wrote such code,
then complained when the code doesn't port unchanged to a different architecture
or compiler.

The bottom line - if you want to *portably* encode/decode bytestreams of this
nature you have to do it one byte at a time. There is no other way to ensure
that the same code will work across different architectures. Wanna encode a
16 bit value as two sequential bytes? Do it like this:

	*cp++ = (val & 0xFF);
	*cp++ = (val >> 8) & 0xFF;

The masking is redundant, but makes it clear what you're doing, and will be
optimized away by any decent compiler.

Now if you happen to have code that someone naively wrote that only works
on one particular architecture - don't expect a compiler to save you. Just
bite the bullet, rewrite the code properly, and learn from the experience.
It will save you a LOT of time in the long run.

Re: [lpc2000] Re: For C novices

2006-03-31 by Robert Adsett

Quoting Clyde Stubbs <clyde@...>:

> On Fri, Mar 31, 2006 at 02:20:12AM -0000, garycordelli wrote:
>> Just a postscript: this is not an academic notion to which I allude,
>> but a common error in just the kind of code I am paid to fix every day.
>>
>> The circumstances tend to be communications code, where the programmer
>> has created a generic n-byte buffer:
>
<snip>
> The bottom line - if you want to *portably* encode/decode bytestreams of this
> nature you have to do it one byte at a time. There is no other way to ensure
> that the same code will work across different architectures.

Amen.  Do it right, save yourself future headaches.  Separate the 
communications
format from the internal structure. Even if they happen to match.

> Wanna encode a
> 16 bit value as two sequential bytes? Do it like this:
>
> 	*cp++ = (val & 0xFF);
> 	*cp++ = (val >> 8) & 0xFF;
>
> The masking is redundant, but makes it clear what you're doing, and will be
> optimized away by any decent compiler.

The harder part is going the other way and making sure things get sign 
extended
properly, especially if communication size and internal storage size don't
match.

As a for instance I've seen CAN protocols that use a 10bit signed int 'across
the wire'

> Now if you happen to have code that someone naively wrote that only works
> on one particular architecture - don't expect a compiler to save you. Just
> bite the bullet, rewrite the code properly, and learn from the experience.
> It will save you a LOT of time in the long run.

And get yourself a good lint, theres a good chance there are more 
gotchas hidden
in the code.

Robert

Re: For C novices

2006-03-31 by garycordelli

Yes, indeed.

In fact, portable communications code often includes functions (or
macro equivalents) that -- assuming the external comms is, like TCP,
undertaken in big-endian byte order -- look like (written here for
clarity, not efficiency):

int32 ExtractInt32(char *p)
{
    int32 value;

    // (note: mask bits to ignore sign-extend on bytes >= 0x80)
#ifdef BIGENDIAN_CPU  
    // extract bytes to big-endian storage (matches buffer order)
    value = p[0]; // skip mask, since sign-extend bits will shift off
    value = (value << 8) | (p[1] & 0x00FF);
    value = (value << 8) | (p[2] & 0x00FF);
    value = (value << 8) | (p[3] & 0x00FF);
#else  
    // extract bytes to little-endian storage (opposite buffer order)
    value = p[3]; // skip mask, since sign-extend bits will shift off
    value = (value << 8) | (p[2] & 0x00FF);
    value = (value << 8) | (p[1] & 0x00FF);
    value = (value << 8) | (p[0] & 0x00FF);
#endif
    return value;
}

void InsertInt32(int32 value, char *p)
{
    // (note: conversion is done implicitly, but cast avoids warning)
#ifdef BIGENDIAN_CPU  
    // assign bytes from big-endian mutli-byte storage type
    p[0] = (char)(value >> 24);
    p[1] = (char)(value >> 16);
    p[2] = (char)(value >> 8);
    p[3] = (char)value;
#else  
    // assign bytes from little-endian multi-byte storage type
    p[0] = (char)value;
    p[1] = (char)(value >> 8);
    p[2] = (char)(value >> 16);
    p[3] = (char)(value >> 24);
#endif
}

Then "int32 value = ExtractInt32(p);" can be used to extract 32-bit
integers from the communications buffer on receipt and
"InsertInt32(value, p);" can be used to insert 32-bit integers into
the communications buffer for transmit -- all regardless of alignment
of these fields within the "char buffer[]", and can also automatically
handle differences in the "endianess" of the external communications
byte ordering and the internal CPU byte ordering (just #define/#undef
BIGENDIAN according to what target processor you are compiling for).

Then your internal data structures don't have to care if the message
structures are "compatible" with the processor you are porting to.  It
is ugly and a tad inefficient, but that's the price you pay for
portability.

The above operations are not, despite your strongest desire, the job
of the compiler, but the programmer.

Cordeg


--- In lpc2000@yahoogroups.com, Robert Adsett <subscriptions@...> wrote:
>
> Quoting Clyde Stubbs <clyde@...>:
> 
> > On Fri, Mar 31, 2006 at 02:20:12AM -0000, garycordelli wrote:
> >> Just a postscript: this is not an academic notion to which I allude,
> >> but a common error in just the kind of code I am paid to fix
every day.
> >>
> >> The circumstances tend to be communications code, where the
programmer
> >> has created a generic n-byte buffer:
> >
> <snip>
> > The bottom line - if you want to *portably* encode/decode
bytestreams of this
> > nature you have to do it one byte at a time. There is no other way
to ensure
> > that the same code will work across different architectures.
> 
> Amen.  Do it right, save yourself future headaches.  Separate the 
> communications
> format from the internal structure. Even if they happen to match.
> 
> > Wanna encode a
> > 16 bit value as two sequential bytes? Do it like this:
> >
> > 	*cp++ = (val & 0xFF);
> > 	*cp++ = (val >> 8) & 0xFF;
> >
> > The masking is redundant, but makes it clear what you're doing,
and will be
> > optimized away by any decent compiler.
> 
> The harder part is going the other way and making sure things get sign 
> extended
> properly, especially if communication size and internal storage size
don't
> match.
> 
> As a for instance I've seen CAN protocols that use a 10bit signed
int 'across
> the wire'
> 
> > Now if you happen to have code that someone naively wrote that
only works
> > on one particular architecture - don't expect a compiler to save
you. Just
> > bite the bullet, rewrite the code properly, and learn from the
experience.
Show quoted textHide quoted text
> > It will save you a LOT of time in the long run.
> 
> And get yourself a good lint, theres a good chance there are more 
> gotchas hidden
> in the code.
> 
> Robert
>

Re: For C Experts

2006-03-31 by dsidlauskas1

Paul,

You're not the first one to say I was nuts :-).

However, it might help with my recovery if you coulld elaborate a bit.

Thanks,

Dave S.

--- In lpc2000@yahoogroups.com, "Paul Curtis" <plc@...> wrote:
Show quoted textHide quoted text
>
> Hi, 
> 
> > Since the compiler knows that buf is a byte aligned object, 
> > woutldn't it be resonable for the compiler to treat
> > 
> > (int *)&buf[i]
> > 
> > as 
> > 
> > (__packed int *)&buf[i]
> > 
> > In general, if non-naturaly aligned objects are promoted by a 
> > cast, shouldn't, by default, the cast be of the proper 
> > non-aligned type?
> 
> Bloody hell no.  Insanity.
> 
> --
> Paul Curtis, Rowley Associates Ltd   http://www.rowley.co.uk 
> CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors
>

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.