A89: Re: Re: What is wrong here?


[Prev][Next][Index][Thread]

A89: Re: Re: What is wrong here?




Hi!

>> 1) missing braces around initializer for '(anonymous).xy'
> 
> This is not an error, but a warning.  It is thrown because 
> SCR_RECT is a union.  To get rid of it, just put the extra 
> braces in (double braces around the initializer). If it 
> shows as an error or doesn't compile, please give me some
> additional information (e.g. using IDE or command-line 
> compiler, version of TI-GCC, ...)

Yes. This is somewhat my error guilt too. As I compiled my
first programs without -Wall option, I never received this
warning, so I didn't noticed that extra braces are necessary.
That's why a lot of my programs and examples in the documentation
are with only one braces, so it produce a confusion. I must
rewrite the documentation to correct this.

>> 2) invalid lvalue in unary '&'
> 
> Well, you already know the solution for that:  The initializers
> can only be constants (I think).

No, initializers may be non-constants (in GNU C, but TIGCC is GNU C).
For example, 

int a=3,b=4,c=5,d=6;
SCR_RECT myScr={b+a,b-a,d+c,d-c};

is quite legal. The problem is much more complex. GNU C has one 
extension in addition to ordinary C: cast constructors. This is a
method for constructing structures, arrays, unions etc. "on fly" by
using a typecasting an initializer to appropriate data type, for 
example

(SCR_RECT){{10,10,50,50}}

So, you can use

SCR_RECT myScr;
...
myScr=(SCR_RECT){{10,10,50,50}};

which is impossible in ordinary C (ANSI C). You can even use

myScr=(SCR_RECT){{a,b,c,d}};

where a,b,c,d are expressions. Well, but what is now the problem?
See, C has two type of objects: lvalues and non-lvalues. lvalues
are objects which may appear on the left size of an assignment.
For example, a variable is a lvalue and a constant is not a lvalue,
because x=5 is legal and 5=x (or 5=3) is not legal. Not only
variables are lvalues; for example, dereferenced pointers are also
lvalues, so this is legal for example (store 100 at address 0x4c00):

*(char*)0x4c00=100;

So, *(char*)0x4c00 is a lvalue. Now, about the problem. In GNU C,
cast constructors are lvalues only if the initializer is completely
constant. I.e. (SCR_RECT){{10,10,50,50}} is a lvalue, but
(SCR_RECT){{a,b,c,d}} is not. As C language accepts unary "&"
operator (i.e. "address of") only on lvalue objects, this means
that, for example,

&(SCR_RECT){{10,10,50,50}}

is legal, but

&(SCR_RECT){{a,b,c,d}}

is not! This is the real cause of the problem!!!

What you can do? Declare one SCR_RECT variable, say myScr,

SCR_RECT myScr;

and instead of

ScrRectFill(&(SCR_RECT){0,first_y,SCREEN_WIDTH,first_y+16},ScrRect,A_XOR);

use:

myScr=(SCR_RECT){{0,first_y,SCREEN_WIDTH,first_y+16}};
ScrRectFill(&myScr,ScrRect,A_XOR);

Note that &myScr is legal, because myScr is a lvalue (it is an ordinary
variable).

I hope that this helps a lot understanding of cast constructors and
lvalues.

Cheers,

Zeljko Juric