> "David Brown" <david.brown@hesbynett.removethisbit.no> wrote in message
> news:47a23426$0$14988$8404b019@news.wineasy.se...
>> Wilco Dijkstra wrote:
>>> "David Brown" <david@westcontrol.removethisbit.com> wrote in message
>>> news:47a1a46d$0$14996$8404b019@news.wineasy.se...
>
>>>> there are many architectures with different pointer types and different memory spaces. These don't fit well with C
>>>> (which expects a single memory space), but they are the reality we live with. On an AVR Mega256, a general flash
>>>> pointer will 24 bits, while a ram pointer will be 16 bits. On some architectures you get "far" and "near" pointers.
>>>> There are some that have a section of bit-addressable memory, with a different pointer type. You can't rely on
>>>> these things having a consistent pointer size - you should not even rely on the C requirement of a "void *"
>>>> supporting them all (embedded compilers don't always follow the standards if they conflict with generating good
>>>> object code for real-world source code).
>>> But as you say C doesn't map onto these architectures, so we're not
>>> talking about standard C. Most programs won't compile for these
>>> architectures (assuming the code would fit), and if they did still wouldn't
>>> run correctly - precisely because these architectures do not support the
>>> defacto assumptions that most C programs make.
>>>
>> C doesn't map directly onto these architectures - but that does not stop people using C for them on a regular basis!
>> Look at the AVR, for example - it has different address spaces for flash and ram data, so the pointers are
>> incompatible. On the larger AVRs, a full flash pointer must be 24 bits, while ram pointers are only 16 bits. Yet
>> somehow there are vast numbers of these devices in use, almost all of them programmed in C. You certainly can't take
>> a random C program off the internet and expect it to compile and work on an AVR, but there is no problem writing
>> portable code that works on the 8-bit AVR, 16-bit msp430, 32-bit big-endian ColdFire, 32-bit little-endian ARM, and
>> even some of these horrible DSP architectures with their 16-bit chars. You just have to stick to assumptions that are
>> appropriate for embedded programming, rather than thinking "big" C.
>
> There are indeed architectures which can't fully support standard C. You
> can indeed write standard conforming programs on these if you avoid
> any of the default assumptions (casting pointers being one of them) and
> use macros to map the differences (assuming you know all of them).
>
It depends on how much the target differs from being a good C target,
and what kind of code you are writing. For example, the AVR cannot
access flash data using the same kind of pointer as ram data. If you
are writing code that uses a constant table, you have three possible
choices - you can waste large amounts of precious ram keeping a copy of
the table, so that normal ram data pointers can be used, you can write
compiler/target specific code, or you can write code that includes
special wrapper functions/macros for all table access, with these being
defined according to the compiler/target combination in use. None of
these are practical - in reality, such code will be written using the
"flash" keyword if you are using IAR, a slightly non-standard abuse of
"const" if you are using ImageCraft, and "progmem" and assorted macros
if you are using avr-gcc.
> However this illustrates the difference between "it just works" and putting
> a lot of effort into making it work. Most software isn't specifically written to
> be portable, and yet porting is surprisingly easy. You can download random
> source code from the internet and expect it to compile and work on ARM,
> MIPS, PPC, ColdFire, AVR32 or any other modern embedded architecture
> with minimal effort.
>
In the context of embedded development, all of these processors listed
are fairly "big". They are all 32-bit processors with good support for
C, and thus you can expect that code "just works". Portability issues
(for general code that is not interfacing directly with hardware) come
to light when using smaller or more specialised processors.
>>> The reverse is true as well, programs written for these C dialects do not
>>> work on standard C compilers. One case that comes up often is:
>>> unsigned char c = 255; if (~c == 0) ... This is always false in standard C,
>>> but there are compilers which think it is true...
>>>
>> If code like that comes up "often", you have bigger problems than just bad assumptions - that code snippet is
>> horrible. But it is certainly true that code written for small embedded C systems often has compiler/target specific
>> features that don't work on larger systems - code for a compiler with an extra "flash" keyword for flash-based data
>> will clearly not compile on anything else without some changes.
>
> It was an example of what goes wrong when people try to port applications
> when moving to a different architecture, and find that their code doesn't
> work any more. Some 8-bit compilers apparently don't apply the standard
> integer promotion rules, which makes porting of all but the most trivial
> programs rather tricky.
>
I've more often had issues with 8-bit compilers producing correct but
inefficient code due to C's promotion rules, but I get the point.
Reply by Wilco Dijkstra●February 5, 20082008-02-05
"David Brown" <david.brown@hesbynett.removethisbit.no> wrote in message
news:47a23426$0$14988$8404b019@news.wineasy.se...
> Wilco Dijkstra wrote:
>> "David Brown" <david@westcontrol.removethisbit.com> wrote in message
>> news:47a1a46d$0$14996$8404b019@news.wineasy.se...
>>> there are many architectures with different pointer types and different memory spaces. These don't fit well with C
>>> (which expects a single memory space), but they are the reality we live with. On an AVR Mega256, a general flash
>>> pointer will 24 bits, while a ram pointer will be 16 bits. On some architectures you get "far" and "near" pointers.
>>> There are some that have a section of bit-addressable memory, with a different pointer type. You can't rely on
>>> these things having a consistent pointer size - you should not even rely on the C requirement of a "void *"
>>> supporting them all (embedded compilers don't always follow the standards if they conflict with generating good
>>> object code for real-world source code).
>>
>> But as you say C doesn't map onto these architectures, so we're not
>> talking about standard C. Most programs won't compile for these
>> architectures (assuming the code would fit), and if they did still wouldn't
>> run correctly - precisely because these architectures do not support the
>> defacto assumptions that most C programs make.
>>
>
> C doesn't map directly onto these architectures - but that does not stop people using C for them on a regular basis!
> Look at the AVR, for example - it has different address spaces for flash and ram data, so the pointers are
> incompatible. On the larger AVRs, a full flash pointer must be 24 bits, while ram pointers are only 16 bits. Yet
> somehow there are vast numbers of these devices in use, almost all of them programmed in C. You certainly can't take
> a random C program off the internet and expect it to compile and work on an AVR, but there is no problem writing
> portable code that works on the 8-bit AVR, 16-bit msp430, 32-bit big-endian ColdFire, 32-bit little-endian ARM, and
> even some of these horrible DSP architectures with their 16-bit chars. You just have to stick to assumptions that are
> appropriate for embedded programming, rather than thinking "big" C.
There are indeed architectures which can't fully support standard C. You
can indeed write standard conforming programs on these if you avoid
any of the default assumptions (casting pointers being one of them) and
use macros to map the differences (assuming you know all of them).
However this illustrates the difference between "it just works" and putting
a lot of effort into making it work. Most software isn't specifically written to
be portable, and yet porting is surprisingly easy. You can download random
source code from the internet and expect it to compile and work on ARM,
MIPS, PPC, ColdFire, AVR32 or any other modern embedded architecture
with minimal effort.
>> The reverse is true as well, programs written for these C dialects do not
>> work on standard C compilers. One case that comes up often is:
>> unsigned char c = 255; if (~c == 0) ... This is always false in standard C,
>> but there are compilers which think it is true...
>>
>
> If code like that comes up "often", you have bigger problems than just bad assumptions - that code snippet is
> horrible. But it is certainly true that code written for small embedded C systems often has compiler/target specific
> features that don't work on larger systems - code for a compiler with an extra "flash" keyword for flash-based data
> will clearly not compile on anything else without some changes.
It was an example of what goes wrong when people try to port applications
when moving to a different architecture, and find that their code doesn't
work any more. Some 8-bit compilers apparently don't apply the standard
integer promotion rules, which makes porting of all but the most trivial
programs rather tricky.
Wilco
Reply by aamer●February 4, 20082008-02-04
Hi all,
The problem is solved using proper type casting.
thanks
>
>"Hans-Bernhard Br?" <HBBroeker@t-online.de> wrote in message
news:fnqrev$3ei$01$1@news.t-online.com...
>> Paul Keinanen wrote:
>>
>>> In which case would an arbitrary pointer casting be a problem ?
>>
>> Roughly all of them. The real question is how violently the problem
will show itself. Some of them can lie dormant
>> for a decade before a platform change exposes them as total
show-stoppers.
>>
>>> With any byte addressable architecture, a pointer is just a pointer.
>>
>> But there are quite a few non-byte addressable architectures out
there.
>> Including ARM, last I checked.
>
>Actually most architectures are byte addressable, including ARM, so
>casting pointers just works. Of course it's essential to know what
you're
>doing - well written programs rarely need pointer casts.
>
>Wilco
>
>
>
Reply by CBFalconer●February 1, 20082008-02-01
Walter Banks wrote:
>
... snip ...
>
> A lot of C99 saw that portability of expression is as important
> as portability of the applications. MISRA did a lot to point
> this out in several areas and many of their concerns were
> adopted. (Sorry Chris but C will steal good idea's whatever the
> source) One of these that we have found makes a difference is
> the size specific data types in addition to the natural data
> sizes of the processor.
While there may well be cases where those specific types are
useful, I firmly believe that the first requirement is to avoid
them. They usually limit portability, and the C standard
guarantees for the values storable in char, short, int, long, (and
even long long for C99) will usually suffice. If your source uses
only these (and derived, such as struct) types portability is
enhanced.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
--
Posted via a free Usenet account from http://www.teranews.com
Reply by Walter Banks●February 1, 20082008-02-01
Wilco Dijkstra wrote:
> > there are many architectures with different pointer types and different memory spaces. These don't fit well with C
> > (which expects a single memory space), but they are the reality we live with. On an AVR Mega256, a general flash
> > pointer will 24 bits, while a ram pointer will be 16 bits. On some architectures you get "far" and "near" pointers.
> > There are some that have a section of bit-addressable memory, with a different pointer type. You can't rely on these
> > things having a consistent pointer size - you should not even rely on the C requirement of a "void *" supporting them
> > all (embedded compilers don't always follow the standards if they conflict with generating good object code for
> > real-world source code).
>
> But as you say C doesn't map onto these architectures, so we're not
> talking about standard C. Most programs won't compile for these
> architectures (assuming the code would fit), and if they did still wouldn't
> run correctly - precisely because these architectures do not support the
> defacto assumptions that most C programs make.
>
> The reverse is true as well, programs written for these C dialects do not
> work on standard C compilers. One case that comes up often is:
> unsigned char c = 255; if (~c == 0) ... This is always false in standard C,
> but there are compilers which think it is true...
Portability comes in two forms. In one case portability is transferring
programs from one target to another. Applications that run on the
desktop PC are unlikely to port to small processors like the RS08,
AVR and the microchip PIC. Individual functions however might
port easily with no or minimal changes.
There is another definition of portability that is not talked about
enough and that is the ability to have a common language to describe
a problem on a wide range of targets. The language offers portability
of expression independent of the features and limitations of the target.
A lot of C99 saw that portability of expression is as important as
portability of the applications. MISRA did a lot to point this out in
several areas and many of their concerns were adopted. (Sorry Chris
but C will steal good idea's whatever the source) One of these that we
have found makes a difference is the size specific data types in addition
to the natural data sizes of the processor.
Regards,
--
Walter Banks
Byte Craft Limited
Tel. (519) 888-6911
Fax (519) 746 6751
http://www.bytecraft.com
walter@bytecraft.com
>
>> there are many architectures with different pointer types and
>> different memory spaces. These don't fit well with C (which
>> expects a single memory space), but they are the reality we live
>> with. On an AVR Mega256, a general flash pointer will 24 bits,
>> while a ram pointer will be 16 bits. On some architectures you
>> get "far" and "near" pointers. There are some that have a
>> section of bit-addressable memory, with a different pointer type.
>> You can't rely on these things having a consistent pointer size
>> - you should not even rely on the C requirement of a "void *"
>> supporting them all (embedded compilers don't always follow the
>> standards if they conflict with generating good object code for
>> real-world source code).
>
> But as you say C doesn't map onto these architectures, so we're
> not talking about standard C. Most programs won't compile for
> these architectures (assuming the code would fit), and if they
> did still wouldn't run correctly - precisely because these
> architectures do not support the defacto assumptions that most
> C programs make.
>
> The reverse is true as well, programs written for these C
> dialects do not work on standard C compilers. One case that
> comes up often is: unsigned char c = 255; if (~c == 0) ... This
> is always false in standard C, but there are compilers which
> think it is true...
True, as long as you keep it in mind. Also, bear in mind that
things written to the specification of standard C will generally
work everywhere. You don't need to rewrite it when porting. If
you get in the habit of writing standard code, and add peculiar
interface files as needed, you will avoid much rewriting in
future. If nothing else well selected functions are portable to
completely new applications.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
--
Posted via a free Usenet account from http://www.teranews.com
Reply by David Brown●January 31, 20082008-01-31
Wilco Dijkstra wrote:
> "David Brown" <david@westcontrol.removethisbit.com> wrote in message news:47a1a46d$0$14996$8404b019@news.wineasy.se...
>> Wilco Dijkstra wrote:
>>> "CBFalconer" <cbfalconer@yahoo.com> wrote in message news:47A11649.3D617492@yahoo.com...
>>>> Wilco Dijkstra wrote:
>>>> ... snip ...
>>>>> My point was that the bitpatterns of all pointer types are the
>>>>> same for all addresses in the address space.
>>>> Not necessarily so. void* carries all the information, apart from
>>>> the object type. void* bitpattern is identical with the char*
>>>> bitpattern, but after that there are no limits.
>>> You're talking about what the C language standards guarantee.
>>> I'm talking about how compilers implement the language. On a
>>> byte addressable architecture you can rely on the one I mentioned
>>> above. The fact is most programs rely on this whether the standard
>>> permits it or not...
>>>
>> It's a fair point that there is a difference what you can rely on for real, practical C and what the standards say.
>> You can happily rely on things like 2's complement arithmetic, and data sizes being 8, 16, 32, 64 bits - if you are
>> programming a dinosaur mainframe, you are probably aware of the fact!
>
> Most programs also rely on signed arithmetic not trapping, signed
> right shifts working as expected, division rounding as expected, char
> being 8-bit and ASCII...
>
All of this is reasonable enough in practice. Of course, some programs
also rely on "char" being signed or unsigned, or "int" being 32-bit, and
other things that may be true on one commonly used compiler/target but
not others.
>> And often when programming, you know exactly what compiler and target you are using, and can program accordingly
>> rather than writing generic code.
>>
>> However, you *can't* rely on pointers working like you describe in general - not in embedded programming. Aside from
>> alignment problems (which may mean that using the pointer does not "just work", even if conversions back and forth
>> do),
>
> As I said derefencing is another issue altogether. Casting is not always
> done in order to dereference, I often use pointer casts to allow comparisons
> between pointers (eg. range check), to align a pointer (to avoid alignment
> issues!) or add an integer to a pointer etc.
>
>> there are many architectures with different pointer types and different memory spaces. These don't fit well with C
>> (which expects a single memory space), but they are the reality we live with. On an AVR Mega256, a general flash
>> pointer will 24 bits, while a ram pointer will be 16 bits. On some architectures you get "far" and "near" pointers.
>> There are some that have a section of bit-addressable memory, with a different pointer type. You can't rely on these
>> things having a consistent pointer size - you should not even rely on the C requirement of a "void *" supporting them
>> all (embedded compilers don't always follow the standards if they conflict with generating good object code for
>> real-world source code).
>
> But as you say C doesn't map onto these architectures, so we're not
> talking about standard C. Most programs won't compile for these
> architectures (assuming the code would fit), and if they did still wouldn't
> run correctly - precisely because these architectures do not support the
> defacto assumptions that most C programs make.
>
C doesn't map directly onto these architectures - but that does not stop
people using C for them on a regular basis! Look at the AVR, for
example - it has different address spaces for flash and ram data, so the
pointers are incompatible. On the larger AVRs, a full flash pointer
must be 24 bits, while ram pointers are only 16 bits. Yet somehow there
are vast numbers of these devices in use, almost all of them programmed
in C. You certainly can't take a random C program off the internet and
expect it to compile and work on an AVR, but there is no problem writing
portable code that works on the 8-bit AVR, 16-bit msp430, 32-bit
big-endian ColdFire, 32-bit little-endian ARM, and even some of these
horrible DSP architectures with their 16-bit chars. You just have to
stick to assumptions that are appropriate for embedded programming,
rather than thinking "big" C.
> The reverse is true as well, programs written for these C dialects do not
> work on standard C compilers. One case that comes up often is:
> unsigned char c = 255; if (~c == 0) ... This is always false in standard C,
> but there are compilers which think it is true...
>
If code like that comes up "often", you have bigger problems than just
bad assumptions - that code snippet is horrible. But it is certainly
true that code written for small embedded C systems often has
compiler/target specific features that don't work on larger systems -
code for a compiler with an extra "flash" keyword for flash-based data
will clearly not compile on anything else without some changes.
Reply by Stefan Reuther●January 31, 20082008-01-31
Wilco Dijkstra wrote:
> "Grant Edwards" <grante@visi.com> wrote in message news:13q21msqkij3dbb@corp.supernews.com...
>>>so casting pointers just works.
>>
>>Unless the resulting pointer is misaligned.
>
> Or the pointer is aligned but points to the wrong place, or invalid memory,
> or a peripheral, or ... If you don't know what you're doing then pointer
> casting is likely the least of your problems.
>
> My point was that the bitpatterns of all pointer types are the same for
> all addresses in the address space.
If they are in the same address space. "void*" (and therefore "char*")
is guaranteed to be able to point at any data item, but there still are
function pointers, which can live in a completely different address
space. The simplest example is our beloved i386 architecture, where data
pointers can be between 16 and 48 bits, code pointers too, but not
necessarily the same size as the others.
Stefan
Reply by Michael N. Moran●January 31, 20082008-01-31
Paul Keinanen wrote:
> With any byte addressable architecture, a pointer is just
> a pointer.
Ever used a strict harvard architecture device like say ...
an Atmel AVR? In the AVR you'll find that pointers to Flash
and pointers to RAM are two entirely separate creatures.
And yet, both types are byte addressable.
--
Michael N. Moran (h) 770 516 7918
5009 Old Field Ct. (c) 678 521 5460
Kennesaw, GA, USA 30144 http://mnmoran.org
"So often times it happens, that we live our lives in chains
and we never even know we have the key."
"Already Gone" by Jack Tempchin (recorded by The Eagles)
The Beatles were wrong: 1 & 1 & 1 is 1
Reply by Wilco Dijkstra●January 31, 20082008-01-31
"David Brown" <david@westcontrol.removethisbit.com> wrote in message news:47a1a46d$0$14996$8404b019@news.wineasy.se...
> Wilco Dijkstra wrote:
>> "CBFalconer" <cbfalconer@yahoo.com> wrote in message news:47A11649.3D617492@yahoo.com...
>>> Wilco Dijkstra wrote:
>>> ... snip ...
>>>> My point was that the bitpatterns of all pointer types are the
>>>> same for all addresses in the address space.
>>> Not necessarily so. void* carries all the information, apart from
>>> the object type. void* bitpattern is identical with the char*
>>> bitpattern, but after that there are no limits.
>>
>> You're talking about what the C language standards guarantee.
>> I'm talking about how compilers implement the language. On a
>> byte addressable architecture you can rely on the one I mentioned
>> above. The fact is most programs rely on this whether the standard
>> permits it or not...
>>
>
> It's a fair point that there is a difference what you can rely on for real, practical C and what the standards say.
> You can happily rely on things like 2's complement arithmetic, and data sizes being 8, 16, 32, 64 bits - if you are
> programming a dinosaur mainframe, you are probably aware of the fact!
Most programs also rely on signed arithmetic not trapping, signed
right shifts working as expected, division rounding as expected, char
being 8-bit and ASCII...
> And often when programming, you know exactly what compiler and target you are using, and can program accordingly
> rather than writing generic code.
>
> However, you *can't* rely on pointers working like you describe in general - not in embedded programming. Aside from
> alignment problems (which may mean that using the pointer does not "just work", even if conversions back and forth
> do),
As I said derefencing is another issue altogether. Casting is not always
done in order to dereference, I often use pointer casts to allow comparisons
between pointers (eg. range check), to align a pointer (to avoid alignment
issues!) or add an integer to a pointer etc.
> there are many architectures with different pointer types and different memory spaces. These don't fit well with C
> (which expects a single memory space), but they are the reality we live with. On an AVR Mega256, a general flash
> pointer will 24 bits, while a ram pointer will be 16 bits. On some architectures you get "far" and "near" pointers.
> There are some that have a section of bit-addressable memory, with a different pointer type. You can't rely on these
> things having a consistent pointer size - you should not even rely on the C requirement of a "void *" supporting them
> all (embedded compilers don't always follow the standards if they conflict with generating good object code for
> real-world source code).
But as you say C doesn't map onto these architectures, so we're not
talking about standard C. Most programs won't compile for these
architectures (assuming the code would fit), and if they did still wouldn't
run correctly - precisely because these architectures do not support the
defacto assumptions that most C programs make.
The reverse is true as well, programs written for these C dialects do not
work on standard C compilers. One case that comes up often is:
unsigned char c = 255; if (~c == 0) ... This is always false in standard C,
but there are compilers which think it is true...
Wilco