Reply by July 6, 20082008-07-06
Rich Webb wrote:

> I don't have the text of C99 here but from the earlier C89 standard: > > 6.3.4 > Conversions that involve pointers (other than as permitted by the > constraints of 6.3.16.1) shall be specified by means of an explicit cast > > and in 6.3.16.1 Simple Assignment > Constraints > One of the following shall hold: > ... > - both operands are pointers to qualified or unqualified versions of > compatible types > - one operand is a pointer to an object or incomplete type and the other > is a pointer to a qualified or unqualified version of void ... > - the left operand is a pointer and the right is a null pointer constant
Now the question is: do these constraints apply before, or after the semantics of 6.3.16.1 (C99: 6.5.16.1) have been taken care of? These semantics are: In simple assignment (=), the value of the right operand is converted to the type of the assignment expression and replaces the value stored in the object designated by the left operand. The conversion of an integer to a pointer is explicitly allowed earlier (C99: 6.3.2.3p5). So once that's happened, we're looking at an assignment among pointers to compatible types, and all's fine.
> The Rationale from both C89 and C99 state that: > > "Since pointers and integers are now considered incommensurate, the only > integer value that can be safely converted to a pointer is a constant > expression with the value 0. The result of converting any other integer > value, including a non-constant expression with the value 0, to a > pointer is implementation-defined."
It's implementation-defined, and thus not "safe". But that's not the same as being an error. It means that the program isn't fully compliant, i.e. it won't be portable.
> So it sounds like a conforming implementation is not required to accept > an assignment expression where the left-hand side is a pointer type and > the right-hand side is an integer type without an explicit cast.
I don't see how that follows from the quoted definitions. Please note that "implementation-defined result" does _not_ include a compiler refusing to translate the source.
>
Reply by CBFalconer July 5, 20082008-07-05
Hans-Bernhard Br�ker wrote:
> CBFalconer wrote: >> Hans-Bernhard Br�ker wrote: > >>> I'll call. Show why exactly this would be an error. And no, >>> examples of compilers that refuse to accept this don't count as >>> evidence. > >> Because the 'address of PORTD' isn't a valid pointer in standard >> C. >> An address or pointer can involve all sorts of things, such as >> disks, tapes, segments, whatever. If your system has provisions >> to accept such things and convert them to 'pointers' then that >> provision is peculiar to that system. It is NOT portable. > > Yes. But C does have implicit conversions from integers to pointers. > So, while it's not certainly not portable, it's not strictly an error > either.
Which is what I said, in one form or another, and which you snipped. I have restored the 2nd, 3rd, and 4th sentences of my message above. -- [mail]: Chuck F (cbfalconer at maineline dot net) [page]: <http://cbfalconer.home.att.net> Try the download section.
Reply by Rich Webb July 5, 20082008-07-05
On Sat, 05 Jul 2008 20:59:16 +0200, Hans-Bernhard Br&#4294967295;ker
<HBBroeker@t-online.de> wrote:

>CBFalconer wrote: >> Hans-Bernhard Br&#4294967295;ker wrote: > >>> I'll call. Show why exactly this would be an error. And no, >>> examples of compilers that refuse to accept this don't count as >>> evidence. > >> Because the 'address of PORTD' isn't a valid pointer in standard >> C. > >Yes. But C does have implicit conversions from integers to pointers. >So, while it's not certainly not portable, it's not strictly an error >either.
I don't have the text of C99 here but from the earlier C89 standard: 6.3.4 Conversions that involve pointers (other than as permitted by the constraints of 6.3.16.1) shall be specified by means of an explicit cast and in 6.3.16.1 Simple Assignment Constraints One of the following shall hold: ... - both operands are pointers to qualified or unqualified versions of compatible types - one operand is a pointer to an object or incomplete type and the other is a pointer to a qualified or unqualified version of void ... - the left operand is a pointer and the right is a null pointer constant The Rationale from both C89 and C99 state that: "Since pointers and integers are now considered incommensurate, the only integer value that can be safely converted to a pointer is a constant expression with the value 0. The result of converting any other integer value, including a non-constant expression with the value 0, to a pointer is implementation-defined." So it sounds like a conforming implementation is not required to accept an assignment expression where the left-hand side is a pointer type and the right-hand side is an integer type without an explicit cast. -- Rich Webb Norfolk, VA
Reply by July 5, 20082008-07-05
CBFalconer wrote:
> Hans-Bernhard Br&#4294967295;ker wrote:
>> I'll call. Show why exactly this would be an error. And no, >> examples of compilers that refuse to accept this don't count as >> evidence.
> Because the 'address of PORTD' isn't a valid pointer in standard > C.
Yes. But C does have implicit conversions from integers to pointers. So, while it's not certainly not portable, it's not strictly an error either.
Reply by CBFalconer July 4, 20082008-07-04
Hans-Bernhard Br&#4294967295;ker wrote:
> Jack Klein wrote: >> Frank Buss <fb@frank-buss.de> wrote >> >>> INT16* port_d = (INT16*) [put address of PORTD here]; >>> >>> In C++ not adding a cast would be an error. >> >> It would be an error in C as well. > > I'll call. Show why exactly this would be an error. And no, > examples of compilers that refuse to accept this don't count as > evidence.
Because the 'address of PORTD' isn't a valid pointer in standard C. An address or pointer can involve all sorts of things, such as disks, tapes, segments, whatever. If your system has provisions to accept such things and convert them to 'pointers' then that provision is peculiar to that system. It is NOT portable. -- [mail]: Chuck F (cbfalconer at maineline dot net) [page]: <http://cbfalconer.home.att.net> Try the download section.
Reply by July 4, 20082008-07-04
Jack Klein wrote:
> On Thu, 3 Jul 2008 21:51:39 +0200, Frank Buss <fb@frank-buss.de> wrote
>> INT16* port_d = (INT16*) [put address of PORTD here];
>> In C++ not adding a cast would be an error.
> It would be an error in C as well.
I'll call. Show why exactly this would be an error. And no, examples of compilers that refuse to accept this don't count as evidence.
Reply by ChrisQ July 4, 20082008-07-04
Thomas Magma wrote:
>>> ... I'm trying to find the most efficient way to save a 8-bit >>> signed value found on the LSByte of PORTD to a CHAR. That is, the >>> lower byte of PORTD contains a signed integer that is 8-bits >>> wide and I need to save it to a CHAR data type. I don't care what >>> is on the upper byte of PORTD. >> >> Just read the value and assign it to a char variable. Assuming you >> do not need to do anything special to access the port: >> >> #define INT16 [put right type here] >> >> INT16 * port_d = [put address of PORTD here]; char c; >> >> ... c = *port_d;
Better still: c = (char) *port_d; It may work, but you may get a warning. Always using a cast sends a hint to the compiler and makes it clear when reading the code what is actually being done. To be absolutely correct you should have a (const *) when loading the absolute address and cast this to the pointer type as well. This is the sort of construct I usually use: volatile U16 *pu16RegisterPtr = (U16 * const) REGISTER_ADDRESS; Got this originally from Harbison & Steele and it seems to be correct. The volatile keyword is telling the compiler that no part of the expression should be changed or optimised in any way, while the const keyword tells the compiler that this is, as expected a fixed value. Chris
>
Reply by Frank Buss July 4, 20082008-07-04
Jack Klein wrote:

> On Thu, 3 Jul 2008 21:51:39 +0200, Frank Buss <fb@frank-buss.de> wrote >> >> You should add a cast to avoid compiler warnings for C compilers: >> >> INT16* port_d = (INT16*) [put address of PORTD here]; >> >> In C++ not adding a cast would be an error. > > It would be an error in C as well.
This depends on the compiler. E.g. with GCC 3.4.4 it is a warning, but with ICC08 6.11 it is an error. -- Frank Buss, fb@frank-buss.de http://www.frank-buss.de, http://www.it4-systems.de
Reply by Jack Klein July 3, 20082008-07-03
On Thu, 3 Jul 2008 21:51:39 +0200, Frank Buss <fb@frank-buss.de> wrote
in comp.arch.embedded:

> Roberto Waltman wrote: > > > #define INT16 [put right type here] > > You should use typedef instead of #define > > > INT16 * port_d = [put address of PORTD here]; > > You should add a cast to avoid compiler warnings for C compilers: > > INT16* port_d = (INT16*) [put address of PORTD here]; > > In C++ not adding a cast would be an error.
It would be an error in C as well. -- Jack Klein Home: http://JK-Technology.Com FAQs for comp.lang.c http://c-faq.com/ comp.lang.c++ http://www.parashift.com/c++-faq-lite/ alt.comp.lang.learn.c-c++ http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
Reply by Frank Buss July 3, 20082008-07-03
Thomas Magma wrote:

> Thanks Roberto, I guess this would make sense if the data representation of > the dsPIC33 using the C30 compiler was stored in little endian format. Do > you know if it is for sure?
This would be a problem, if you access a union or cast the int* to char*, but if you first read the int* and then assign it to an char, endian doesn't matter, the lower 8 bits are used all the time, which is what you asked for. Of course, if you read the 16 bit value from PORTD, endian could be a problem. -- Frank Buss, fb@frank-buss.de http://www.frank-buss.de, http://www.it4-systems.de