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



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