A: |
Click here to see everything about GNU C
extensions. But if you are lazy to read too much, I will be more concrete
here. First, in GNU C (TIGCC is GNU C), initializers may be non-constants.
For example,
int a = 3, b = 4, c = 5, d = 6;
int array[4] = {a, b, c, d};
is quite legal. That's why
int a = 3, b = 4, c = 5, d = 6;
SCR_RECT myScr = {{b + a, b - a, d + c, d - c}};
is quite legal too. Second, GNU C has one very nice
extension in addition to ordinary C: cast constructors. This is a
method for constructing structures, arrays, unions etc. "on fly" by
using a typecasting of an initializer to an 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 an lvalue and a constant is not an 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 an 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 an 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 if you need an address of non-constant cast constructor? You need
to declare an auxilary variable. For example, declare one
SCR_RECT variable, say myScr,
SCR_RECT myScr;
and instead of
ScrRectFill (&(SCR_RECT){{a, b, c, d}}, ScrRect, A_XOR);
use:
myScr = (SCR_RECT){{a, b, c, d}};
ScrRectFill (&myScr, ScrRect, A_XOR);
Note that '&myScr' is legal, because 'myScr' is
an lvalue (it is an ordinary variable). I hope that this helps a lot
understanding of cast constructors and lvalues.
|