C - struct中的declare和init数组

时间:2017-12-06 20:15:31

标签: c arrays struct initialization declaration

语言: C

我正在尝试声明并初始化结构中的数组并将其传递给指针,该指针本身在struct xD中声明

是的,我知道我的尝试是......让我们说“不正确”:D 但如果存在类似的东西,那将非常有用。

任何想法?

struct structname {
    int* section_A;
    int* section_B;
};

static const struct structname structvariable_a = {

    .section_A = (int[]) {
            [0x01] = 1,
            [0x02] = 2,
            [0x03] = 3
        },

    .section_B = (int[]) {
            [0x33] = 4,
            [0x34] = 5
        },

};

static const struct structname structvariable_b = {

    .section_A = (int[]) {
            [0x01] = 10,
            [0x02] = 20,
            [0x03] = 30
        },

    .section_B = (int[]) {
            [0x33] = 7,
            [0x34] = 8
        },

};

稍后,我想访问值...

int main()
{

    struct structname* structvariablepointer;

    if(foo == 1){
        structvariablepointer = &structvariable_a;
    } else {
        structvariablepointer = &structvariable_b;
    }

    printf("%i", ARRAY_SIZE(structvariablepointer->section_A));     // ARRAY_SIZE(arr) equals sizeof(arr) / sizeof(arr[0]));

    int b = 2;

    printf("%i", structvariablepointer->section_A[b]);
}

唯一的错误是

./include/linux/build_bug.h:29:45: Fehler: Negative Breite in Bitfeld »<anonym>«
 #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:(-!!(e)); }))
                                             ^
./include/linux/compiler-gcc.h:64:28: Anmerkung: bei Substitution des Makros »BUILD_BUG_ON_ZERO«
 #define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
                            ^~~~~~~~~~~~~~~~~
./include/linux/kernel.h:60:59: Anmerkung: bei Substitution des Makros »__must_be_array«
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
                                                           ^~~~~~~~~~~~~~~

3 个答案:

答案 0 :(得分:1)

  

我正在尝试声明并初始化结构中的数组并将其传递给指针,该指针本身在struct xD中声明

这没有任何意义,但在C99及更高版本中,您的实际代码几乎完全正确。特别是:

(int[]) {
            [0x01] = 1,
            [0x02] = 2,
            [0x03] = 3
        }

既不是数组的初始化声明也不是(相当)初始化;相反,它是int数组类型的复合文字。因为数组在给定的上下文中衰减为指针,就像在大多数情况下一样,这样的复合文字确实可以用于初始化类型int *的结构成员(指向数组的第一个元素)。成功初始化这两个struct structname对象后,您当然可以获取它们的地址并将其记录在变量中。

但是,指向数组元素的指针不包含有关数组中元素数量的信息。如果你拥有的就是main()函数中的情况,那么就无法确定数组元素的数量。您需要能够从内容中确定(这就是C字符串必须以空值终止的原因),或者您必须从其他来源获取该信息,例如函数参数,变量或透视。

  

是的,我知道我的尝试是......让我们说“不正确”:D但是如果存在类似的东西会非常有用。

如果您声明struct structname的成员是真正的数组,那么您可以访问并使用其声明的长度。如果您愿意,可以将数组元素的数量存储在该结构的其他成员中。这两种方法都是在野外使用的,基于指向元素的内容的方法也是如此。但是我不认为C会像你想要的那样获得使你的ARRAY_SIZE()宏用指针工作的工具。

答案 1 :(得分:0)

一旦指针指向数组的第一个元素,就无法再通过该指针找到数组的大小。因此,您还需要创建变量来保存数组大小。 (或者在数组末尾使用sentinel值。)

解决问题的一种方法是通过丑陋的宏:

#include <stddef.h>
#define ARRAY_SIZE(a) ( (sizeof(a)) / sizeof((a)[0]) )


struct structname {
    int* section_A;
    size_t A_len;
    int* section_B;
    size_t B_len;
};

#define A_INIT (int[]) { 0, 1, 2, 3 }
#define B_INIT (int[]) { [0x33] = 1, [0x34] = 2 }

static const struct structname structvariable_a =
{
    .section_A = A_INIT,
    .A_len = ARRAY_SIZE(A_INIT),
    .section_B = B_INIT,
    .B_len = ARRAY_SIZE(B_INIT)
};
#undef A_INIT
#undef B_INIT

还可以定义static名为int的数组,然后在structvariable_a的初始值设定项中使用该数组的名称。

如果您不打算在运行时更改数组的内容,请分别考虑使用int const *int const[]。请注意,如果此代码位于标题中,则每个翻译单元都将拥有自己的数组副本。

更新(根据评论建议):使用sentinel值看起来像:

struct structname {
    int* section_A;
    int* section_B;
};

static const struct structname structvariable_a = 
{
    .section_A = (int[]) { 0, 1, 2, 3, INT_MAX },
    .section_B = (int[]) { [0x33] = 1, [0x34] = 2, INT_MAX }
};

和in main或者其他什么,你找INT_MAX来知道数组末尾的位置,例如:

size_t a_len;
for (a_len = 0; structvariable_a.section_A[a_len] != INT_MAX; ++a_len) { }

显然,这意味着数组的有效数据范围需要排除sentinel值。

答案 2 :(得分:0)

您获得的错误是因为ent需要一个数组,ARRAY_SIZE不是数组而是指针。

由于你的结构有效地具有固定大小的数组,只需将它们声明为数组而不是指针:

structvariablepointer->section_A

然后像这样初始化:

struct structname {
    int section_A[4];
    int section_B[0x35];
};
相关问题