Thomas Ward <[EMAIL PROTECTED]> wrote:
> StrPrintF(display_string, "%s:%c:%s", "str1", 'R', "str");

fails, but

> char    c = 'R';
> StrPrintF(display_string, "%s:%c:%s", "str1", c, "str2");

works.

Heh.  I was wondering how long it would be before somebody noticed
this one :-).  Here's what's really going on.

It all boils down to what type you want 'tFRM' to have.  In Standard
C, all char constants -- like both 'R' and 'tFRM' -- have type *int*.
In the Palm OS ABI, int is only 16 bits, and that's not enough to
represent 32 bit things like creator ids and resource types and so on.

(The obvious answer is not to try to use char constants for these things,
but it's too late for that.  And before anyone claims that multichar
char constants are implementation-defined and we can do what we like,
note that their *values* are implementation-defined, but their *type*
is required to be int.)

Neither CW nor m68k-palmos-gcc implements Standard C in this regard.

CW hacks it so that 'a' and 'ab' are of type int (16 bits, or 32 bits
if 4 byte ints is turned on) while 'abc' and 'abcd' are of type long
(32 bits).  m68k-palmos-gcc hacks it so that all four are of type
long (32 bits).  This is a Palm OS-specific hack to GCC -- stock GCC
follows the Standard.

On the face of it, it's hard to say which one of these behaviours is
more broken.  It's probably fair to say that the CW behaviour is more
convenient -- although possibly more confusing if you do run into
problems.

The situation is a little different in C++.  In Standard C++, char
literals like 'a' have type *char*, while multichar ones like 'tFRM'
have type *int*.  In CW C++, 'a' is char (8 bits), 'ab' is int (16 bits),
and 'abc' and 'abcd' are long (32 bits).  In m68k-palmos-g++, 'a' is char
(8 bits) and the rest are all long (32 bits).

(This means that Thomas's first example would work fine in C++, both
in CW C++ and m68k-palmos-g++.)

Amusingly enough, if you used 32 bit ints ("4 byte ints" in CW or
"-mnoshort" in GCC), the CW hack and the GCC hack would produce the
same results in all cases (both C and C++), and would be in accordance
with the Standards.  But doing that would lead to problems in itself --
see http://www.escribe.com/computing/pcpqa/m10208.html .

I think the progression of types in C++ motivates the CW behaviour,
and fixing m68k-palmos-gcc to agree with this has been on my list for
a while.  It hasn't been done yet because I am interested to see whether
Apple have already run in to this issue.

Thomas has stumbled on to one of the very few ways to actually detect
the difference.  I can only think of two ways in C and three in C++.
(Anyone?  :-))

Note that all this only applies to unadorned char constants/literals.
If you have an explicit char variable like the second example above,
or if you explicitly cast to char -- (char)'R' -- or int, the expression
will have the type which %c is expecting (*) and everything will be fine.

    John

(* which isn't char, btw.  Consequently, answers like

[Roger Chaplin]
> When the compiler sees the literal 'R', it creates an int having the
> value 82. You've told StrPrintF to expect a char at that place in the
> argument list. That's why you don't get the error if you use
> char    c = 'R';

are, I fear, quite wrong.  C's calling conventions specifically cater for
alignment issues like this.  See http://www.eskimo.com/~scs/C-faq/q15.10.html )

-- 
For information on using the Palm Developer Forums, or to unsubscribe, please see 
http://www.palmos.com/dev/tech/support/forums/

Reply via email to