C中结构数组的静态初始化

时间:2011-11-20 21:16:08

标签: c arrays initialization struct

我有一个关于C语言结构数组初始化的问题。谷歌搜索告诉我很多人都有非常相似的问题,但它们并不完全相同。

基本上,我有一个全局的结构类型“memPermissions”,如下所示。 在程序执行时,该数组需要将所有“address”和“ownerId”字段初始化为-1。

typedef struct memPermissions {
    int address;
    int ownerId;
} *test;

问题是数组是使用#define调整大小的,所以我不能简单地去:

#define numBoxes 5

struct memPermissions memPermissions[numBoxes] = {
{-1, -1},
...
{-1, -1}
};

我试过了:

struct memPermissions memPermissions[numBoxes] = {-1, -1};

但自然这只是初始化了第一个元素。 (其余的被设置为0)。跳到脑海的唯一解决方案是在某处使用简单的循环初始化它,但由于此代码运行的性质,我真的希望这不是我唯一的选择。

有没有办法在没有循环的情况下初始化这个结构数组的所有元素?

干杯, -Josh

5 个答案:

答案 0 :(得分:8)

C99标准添加了各种有用的方法来初始化结构,但没有提供重复运算符(Fortran从那时起就一直存在 - 但可能是为什么没有添加)。

如果您使用的是最新版本的GCC,并且可以使用非便携式扩展程序,那么GCC会提供扩展程序。在GCC 8.1.0手册(§6.27 Designated Initializers)中,它说:

  

要将一系列元素初始化为相同的值,请写入'[first ... last] = value'。   这是一个GNU扩展。例如,

int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };
     

如果其中的值具有副作用,则副作用将仅发生一次,而不是由范围初始值设定项对每个初始化字段发生。

所以,在你的例子中使用它:

struct memPermissions memPermissions[numBoxes] =
{
    [0..numBoxes-1] = {-1, -1},    // GCC extension
};

我希望这是C标准;它会非常有用!


不使用该编程器或其他类似的编译器特定机制,您唯一的选择是循环。对于具有许多字段的复杂初始化程序,并非所有相同的值,您可以使用:

#include <string.h>
#include "memperm.h"  // Header declaring your types and variables

static int initialized = 0;
// -2 so the initialization isn't uniform and memset() is not an option
static const struct memPermissions initPermissions = { -1, -2 };
struct memPermissions memPermissions[numBoxes];

void initialize_permissions(void)
{
    if (initialized == 0)
    {
        for (int i = 0; i < numBoxes; i++)
            memmove(&memPermissions[i], &initPermissions, sizeof(initPermissions));
        initialized = 1;
    }
}

你也可以在这里使用memcpy() - 两个变量没有重叠的危险。

现在你只需要确保在使用数组之前调用initialize_permissions() - 最好只需要一次。可能还有编译器特定的机制来允许这样做。

您可以在initialize_permissions()函数中使用局部变量来代替初始化的静态常量变量 - 只需确保每次调用函数时编译器都不会初始化它。

如果您有C99编译器,则可以使用复合文字代替常量:

void initialize_permissions(void)
{
    if (initialized == 0)
    {
        for (int i = 0; i < numBoxes; i++)
            memmove(&memPermissions[i],&(struct memPermissions){ -1, -2 },
                    sizeof(memPermissions[0]));
        initialized = 1;
    }
}

答案 1 :(得分:2)

您可以编写一个传递所需项目数的外部程序。该程序应由Makefile或同等程序调用。该程序将为您编写一个包含文件,其中包含所需的-1值以及#define

答案 2 :(得分:1)

如果您有可用的标准库,则可以使用memsetsizeof(struct memPermissions) * numBoxes结合使用任何统一字节值填充数组。由于-1在许多平台上都是0xFFFFFFFF,因此这可能对您有用。

答案 3 :(得分:0)

  

跳出来的唯一解决方案是用一个简单的循环初始化它

我担心这是语言中唯一的可能性。在C中,您可以显式初始化每个元素,初始化为全零或不初始化。

但是,您可以使用0来回避此问题,以便-1当前投放。

答案 4 :(得分:-1)

如果不使用循环非常重要,你可以做一些相当奇怪的事情,并假设可用,使用/滥用memset

N.B。 Memset可以使用循环实现,因此可能没有用。

memset(memPermissions, 0xFF, sizeof(memPermissions)*numBoxes*2*sizeof(int));

结构的两个成员(即其中两个)需要时间2。

这个设计很差,因为它取决于结构没有填充或对齐,编译器可以根据C规范自由地执行。

(对于32位处理器上的2-compliment负整数,使用-1通常为0xFFFFFFFF,具有32位int。感谢@James指出这一点。)

虽然在大多数情况下我会怀疑代码将在汇编语言中实现为一个小的,快速的,紧密的循环(rep movsd for x86),除了最微不足道的情况之外(非常小的{ {1}})。