我有一个关于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
答案 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)
如果您有可用的标准库,则可以使用memset
与sizeof(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}})。