C 中结构体数组的静态初始化
我有一个关于 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)。想到的唯一解决方案是在某个地方用一个简单的循环来初始化它,但由于该代码将运行的位置的性质,我真的希望这不是我唯一的选择。
有没有办法在没有循环的情况下初始化这个结构数组的所有元素?
干杯, -乔什
I have a question regarding the initialization of an array of structs in C. Googling showed me that a lot of people have had very similar questions, but they weren't quite identical.
Essentially, I have a global array of structs of type "memPermissions" shown below.
This array needs all the "address" and "ownerId" fields to be initialized to -1 upon program execution.
typedef struct memPermissions {
int address;
int ownerId;
} *test;
The problem is the array is sized using a #define, so I can't simply go:
#define numBoxes 5
struct memPermissions memPermissions[numBoxes] = {
{-1, -1},
...
{-1, -1}
};
I tried:
struct memPermissions memPermissions[numBoxes] = {-1, -1};
But naturally this only initialized the first element. (The rest were set to 0). The only solution that jumps to mind would be to initialize it with a simple loop somewhere, but because of the nature of where this code will run, I'm really hoping that's not my only option.
Is there any way to initialize all the elements of this array of structs without a loop?
Cheers,
-Josh
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
C99 标准添加了各种有用的方法来初始化结构,但没有提供重复运算符(Fortran 一直都有这个操作符 - 但也许这就是它没有添加的原因)。
如果您使用的是足够新的 GCC 版本并且可以使用不可移植的扩展,那么 GCC 会提供一个扩展。在 GCC 8.1.0 手册中 ( §6.27 指定初始化器),它说:
所以,在你的例子中使用这个:
我希望这是在 C 标准中;这会很有帮助的!
如果不使用该机制或其他类似的特定于编译器的机制,您唯一的选择就是循环。对于具有许多字段且值不完全相同的复杂初始值设定项,您可以使用:
您还可以在此处使用 memcpy() - 不存在两个变量重叠的危险。
现在您只需确保在使用数组之前调用
initialize_permissions()
- 最好只调用一次。也可能存在特定于编译器的机制来允许这样做。您可以在
initialize_permissions()
函数中使用局部变量来代替已初始化的静态常量变量 - 只要确保您的编译器不会在每次调用该函数时都对其进行初始化即可。如果您有 C99 编译器,则可以使用复合文字来代替常量:
The C99 standard added all sorts of useful ways to initialize structures, but did not provide a repeat operator (which Fortran has had since forever - but maybe that was why it wasn't added).
If you are using a sufficiently recent version of GCC and you can afford to use a non-portable extension, then GCC provides an extension. In the GCC 8.1.0 manual (§6.27 Designated Initializers), it says:
So, using this in your example:
I wish this were in the C Standard; it would be so helpful!
Without using that or other similar compiler-specific mechanisms, your only choice is a loop. For a complex initializer with many fields, not all the same value, you can probably use:
You can also use
memcpy()
here - there is no danger of the two variables overlapping.Now you just need to ensure that
initialize_permissions()
is called before the array is used - preferably just once. There may be compiler-specific mechanisms to allow that, too.You could use a local variable in the
initialize_permissions()
function in place of the initialized static constant variable - just be sure your compiler doesn't initialize it every time the function is called.If you have a C99 compiler, you can use a compound literal in place of the constant:
您可以编写一个外部程序来传递所需的项目数。该程序应该由您的 Makefile 或等效文件调用。该程序将为您编写一个包含文件,其中包含所需数量的 -1 值以及
#define
。You can write an external program that is passed the number of items that you want. This program should be called by your Makefile or equivalent. The program will write an include file for you with the required number of -1 values as well as the
#define
.如果您有可用的标准库,则可以将
memset
与sizeof(struct memPermissions) * numBoxes
结合使用,用任何统一的字节值填充数组。由于 -1 在许多平台上是0xFFFFFFFF
,因此这可能适合您。If you have the standard library available, you can use
memset
combined withsizeof(struct memPermissions) * numBoxes
to fill your array with any uniform byte value. Since -1 is0xFFFFFFFF
on many platforms, this might work for you.恐怕这是该语言中唯一的可能性。在 C 中,您可以显式初始化每个元素、初始化为全零或不初始化。
但是,您可以通过使用
0
来回避该问题,以达到-1
当前所服务的目的。Which is the only possibility within the language, I'm afraid. In C, you either initialize each element explicitly, initialize to all zeros or don't initialize.
However, you can sidestep the issue by using
0
for the purpose that your-1
currently serves.如果不使用循环确实很重要,那么您可以做一些相当奇怪的事情,并使用/滥用memset(假设可用)。
NB Memset 可以使用循环来实现,因此它可能没有实际意义。
结构体的两个成员(即其中两个)都需要时间 2。
这是设计得很糟糕的,因为它取决于结构没有填充或对齐,而编译器可以根据 C 规范自由地这样做。
(在 32 位处理器上使用
-1
通常为0xFFFFFFFF
表示 2-compliment 负整数,使用 32 位int
。感谢 @ James 指出了这一点。)尽管在大多数情况下,我怀疑代码会以汇编语言实现为一个小、快速、紧密的循环(x86 的
rep movsd
),但除了最简单的情况(numBoxes
的值非常小)。If it really important to not use a loop, you could do something rather strange, and use/abuse
memset
assuming that is available.N.B. Memset may be implemented using a loop, so it may be moot.
The times 2 is needed for both members of the struct (i.e. two of them).
This is poorly designed in that it depends that the struct is not padded or aligned, which the compiler is free to do so as per the C specifications.
(Utilizing that
-1
is typically0xFFFFFFFF
for 2-compliment negative integers on 32-bit processors, with 32-bitint
. Kudos to @James for pointing this out.)Though I would suspect in most cases that the code would be implemented as a small, fast, tight loop (
rep movsd
for x86) in assembly language in all but the most trivial of cases (very small values ofnumBoxes
).