【问题标题】:C - declare and init array inside structC - 在结构中声明和初始化数组
【发布时间】:2018-05-20 20:00:07
【问题描述】:

语言:C

我正在尝试在结构中声明和初始化一个数组并将其传递给一个指针,该指针本身在结构 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))
                                                           ^~~~~~~~~~~~~~~

【问题讨论】:

  • @user-44651 - 您引用的链接标记为 c#,这是一种完全不同的语言,具有不同的规则。 IMO,这不是那个的副本。
  • 在您为int* section_A; 创建空间之前,您在static const struct structname structvariable_b = {... 中引用的元素不存在。如果您知道在编译时会有三个元素,为什么不直接将其创建为:int section_A[3];?一般来说,最好使用堆栈内存,除非直到运行时才能知道某物的大小。
  • 我将删除这个问题,因为没有人支持它 - 因此我不能再问什么了...我有人反对删除,请告诉我。

标签: c arrays struct initialization declaration


【解决方案1】:

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

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

#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[]。请注意,如果此代码位于标头中,则每个翻译单元将拥有自己的数组副本。


更新(如评论所建议):使用标记值如下所示:

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

main 或其他任何地方,您可以查找INT_MAX 以了解数组的末尾在哪里,例如:

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

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

【讨论】:

  • 非常有用 :) 只要我的声誉足够高,我就会投赞成票。谢谢!
  • 你可以为“哨兵”添加一个例子吗?
【解决方案2】:

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

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

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

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

但是,指向数组元素的指针不携带有关数组中元素数量的信息。如果这就是你所拥有的一切,就像你的 main() 函数一样,那么你无法从中确定数组元素的数量。您需要能够从内容中确定这一点(这就是 C 字符串必须以 null 结尾的原因),或者您必须从其他来源获得该信息,例如函数参数、变量或千里眼。

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

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

【讨论】:

  • 我想将您的回答评为“(非常)有用”——但我的声誉太低了。只要我被允许,我也会这样做;)谢谢!
  • 如果只填充两个元素,你能想到任何类似的代码不保留 35 个元素吗?
  • 当然,@flood,您可以使用链表、哈希表或任何数量的其他数据结构。每个都有权衡。有些人仅在比您提供的更稀疏的数据上赢得空间使用。很少,如果有的话,可以像数组版本一样干净地初始化。除非是真正的问题,否则我不会占用空间。
【解决方案3】:

您遇到的错误是因为 ARRAY_SIZE 需要一个数组,而 structvariablepointer-&gt;section_A 不是数组而是指针。

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

struct structname {
    int section_A[4];
    int section_B[0x35];
};

然后像这样初始化:

static const struct structname structvariable_a = {

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

    .section_B = {
            [0x33] = 4,
            [0x34] = 5
        },
};

【讨论】:

  • 谢谢!但我更愿意在编译时计算大小,因为我想让代码尽可能容易扩展:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-15
  • 2021-12-31
  • 1970-01-01
  • 2011-02-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多