Re: [arm-gnu] Getting linker data into a C structure
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [arm-gnu] Getting linker data into a C structure
- To: "Andrew Kohlsmith (mailing lists account)" <aklists@xxxxxxxxxx>
- Subject: Re: [arm-gnu] Getting linker data into a C structure
- From: Nick Clifton <nickc@xxxxxxxxxx>
- Date: Tue, 11 May 2010 10:19:54 +0100
Hi Andrew,
.a = foo,
>
Compile with gcc -c -o constinit.o constinit.c.
extern const long foo;
extern const long *foo;
both fail with the same error.
extern const long foo[];
> Does not.
Simply put it is because the value of "foo" in the first two cases might
change, but the value of "foo" in the last case will not. But, you will
say, the const keyword makes the first two value constant. Not
necessarily. Consider this example:
% cat a.c
extern const int a;
extern void foo (void);
int
main (void)
{
printf ("a = %d\n", a);
foo ();
printf ("a = %d\n", a);
return 0;
}
% cat b.c
int a = 1;
void foo (void) { a = 2; }
% gcc a.c b.c
% ./a.out
a = 1
a = 2
Try changing this test to use arrays and it will fail to compile. You
can change the value of integer types like "long" and pointers like
"long *", but not of arrays like "long[]".
If you want to be more precise the behaviour is because the C language
specification says that this is how the compiler should behave. The
ISO-C99 standard says this:
Section 6.7.8 (Initialization): paragraph 4:
All the expressions in an initializer for an object that has
static storage duration shall be constant expressions or
string literals.
Section 6.6 (Constant Expressions): paragraph 7:
More latitude is permitted for constant expressions in
initializers. Such a constant expression shall be, or
evaluate to, one of the following:
— an arithmetic constant expression,
— a null pointer constant,
— an address constant, or
— an address constant for an object type plus or minus
an integer constant expression.
Section 6.6 (Constant Expressions): paragraph 9:
An address constant is a null pointer, a pointer to an lvalue
designating an object of static storage duration, or a pointer
to a function designator; it shall be created explicitly using
the unary & operator or an integer constant cast to pointer
type, or implicitly by the use of an expression of array or
function type. The array-subscript [] and member-access .
and -> operators, the address & and indirection * unary
operators, and pointer casts may be used in the creation of
an address constant, but the value of an object shall not be
accessed by use of these operators.
This last paragraph is the crucial one. It allows arrays in the
initializer expression but not pointers or scalar types. (Technically
pointers are scalar types).
Cheers
Nick