Possible to Initialize pointer to array of typed variables?

Advertisements

I have been looking at c pointer to array of structs , and trying to apply it to my example.

I arrived at this code snippet, which compiles fine:

#include <stdio.h>

enum test_e {
    eONE,
    eTWO,
    eTHREE,
};
typedef enum test_e test_t;

#define NUMITEMS 12
extern test_t my_arr[NUMITEMS];

test_t (*my_arr_ptr)[NUMITEMS];

test_t my_arr[NUMITEMS] = { 0 };


int main()
{
    my_arr_ptr = &my_arr;
    printf("Hello World %p\n", my_arr_ptr);

    return 0;
}

In the above snippet, we have an assignment of my_arr_ptr variable, to the address of my_arr variable (using the "address of " operator, ampersand &).

However, what I would like to do is to initialize my_arr_ptr variable to the address of my_arr variable – which I’d think is possible, given that after the line test_t my_arr[NUMITEMS] = { 0 }; the compiler should "know" an address and size of my_arr.

However, if I try this:

#include <stdio.h>

enum test_e {
    eONE,
    eTWO,
    eTHREE,
};
typedef enum test_e test_t;

#define NUMITEMS 12
extern test_t my_arr[NUMITEMS];

test_t (*my_arr_ptr)[NUMITEMS];

test_t my_arr[NUMITEMS] = { 0 };

my_arr_ptr = &my_arr;

int main()
{
    //my_arr_ptr = &my_arr;
    printf("Hello World %p\n", my_arr_ptr);

    return 0;
}

… this fails with:

Compilation failed due to following error(s).

main.c:25:1: warning: data definition has no type or storage class
   25 | my_arr_ptr = &my_arr;
      | ^~~~~~~~~~
main.c:25:1: warning: type defaults to ‘int’ in declaration of ‘my_arr_ptr’ [-Wimplicit-int]
main.c:25:1: error: conflicting types for ‘my_arr_ptr’; have ‘int’
main.c:21:10: note: previous declaration of ‘my_arr_ptr’ with type ‘test_t (*)[12]’ {aka ‘enum test_e (*)[12]’}
   21 | test_t (*my_arr_ptr)[NUMITEMS];
      |          ^~~~~~~~~~
main.c:25:14: warning: initialization of ‘int’ from ‘test_t (*)[12]’ {aka ‘enum test_e (*)[12]’} makes integer from pointer without a cast [-Wint-conversion]
   25 | my_arr_ptr = &my_arr;
      |              ^
main.c:25:14: error: initializer element is not computable at load time
main.c: In function ‘main’:
main.c:30:26: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int’ [-Wformat=]
   30 |     printf("Hello World %p\n", my_arr_ptr);
      |                         ~^     ~~~~~~~~~~
      |                          |     |
      |                          |     int
      |                          void *
      |                         %d

As far as I can see, "warning: data definition has no type or storage class" occurs:

because you can’t execute code outside functions
(Why am I getting this error: "data definition has no type or storage class"?)

So, then, is the getting of "address of" considered "code" in C, so I cannot use it outside functions?

If so, how come I can use "address of" operator "outside functions" in the snippet below, which also compiles fine?:

#include <stdio.h>

void func_one(void) {
    printf("func_one\n");
}

void func_two(void) {
    printf("func_two\n");
}

void* funcs_arr[2] = { &func_one, &func_two  }; 

int main()
{
    printf("Hello World %p\n", funcs_arr[0]);

    return 0;
}

>Solution :

The global variables are initialized at their definition. Just do:

extern test_t my_arr[NUMITEMS];

test_t (*my_arr_ptr)[NUMITEMS] = &my_arr;

Addresses of global objects are constant expressions and they can be used to initialize other global objects. See 6.6p7:

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 a complete object type plus or minus an integer constant expression.

The definition of "address constant" can be found at 6.6p9:

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.

Leave a ReplyCancel reply