代码之家  ›  专栏  ›  技术社区  ›  sdbbs

是否可以初始化指向类型化变量数组的指针?

  •  0
  • sdbbs  · 技术社区  · 1 年前

    我一直在看 c pointer to array of structs ,并尝试将其应用于我的示例。

    我得到了这个代码片段,它编译得很好:

    #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;
    }
    

    在上面的片段中,我们有一个 my_arr_ptr 变量,到的地址 my_arr 变量(使用“address of”运算符和 & )。

    然而,我想做的是 初始化 my_arr_ptr 变量的地址 my_arr 变量——我认为这是可能的,因为在这行之后 test_t my_arr[NUMITEMS] = { 0 }; 编译器应该“知道”的地址和大小 my_arr

    但是,如果我尝试这样做:

    #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;
    }
    

    …失败的原因是:

    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
    

    据我所见,出现了“警告:数据定义没有类型或存储类”:

    因为你不能在函数外执行代码
    ( Why am I getting this error: "data definition has no type or storage class"? )

    那么,获取“地址”是否被认为是C中的“代码”,所以我不能在函数外使用它?

    如果是这样的话,为什么我可以在下面的代码段中使用“运算符外部函数的地址”,它也编译得很好?:

    #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;
    }
    
    1 回复  |  直到 1 年前
        1
  •  2
  •   tstanisl    1 年前

    全局变量在其定义时进行初始化。只要做到:

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

    全局对象的地址是常量表达式,可用于初始化其他全局对象。看见 6.6p7 :

    初始值设定项中的常量表达式允许有更多的自由度。此类常量表达式应为或评估为以下其中一种:

    • 算术常数表达式,
    • 空指针常数,
    • 地址常数
    • 完整对象类型的地址常量加上或减去整数常量表达式。

    “地址常数”的定义可在 6.6p9 :

    地址常数是空指针, 指向左值的指针,指定静态存储持续时间的对象 ,或指向函数指示符的指针;应使用一元&运算符或整数常量强制转换为指针类型,或通过使用数组或函数类型的表达式隐式转换。数组下标[]和成员访问。和->运算符,地址&和间接*一元运算符和指针强制转换可以用于创建地址常量,但不能使用这些运算符访问对象的值。