Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 结构中的单元素数组_Arrays_Struct_Element - Fatal编程技术网

Arrays 结构中的单元素数组

Arrays 结构中的单元素数组,arrays,struct,element,Arrays,Struct,Element,为什么某些结构使用单元素数组,如下所示: typedef struct Bitmapset { int nwords; uint32 words[1]; } Bitmapset; 为了方便后面的动态分配?总之,是的 基本上,C99的方法是使用: 一些C99之前版本的编译器可以让您轻松获得: uint32 words[0]; 但保证它在所有编译器中都能工作的方法是: uint32 words[1]; 然后,无论如何声明,您都可以为对象分配: Bitmapset *allocate(int

为什么某些结构使用单元素数组,如下所示:

typedef struct Bitmapset
{
 int nwords;
 uint32 words[1];
} Bitmapset;
为了方便后面的动态分配?

总之,是的

基本上,C99的方法是使用:

一些C99之前版本的编译器可以让您轻松获得:

uint32 words[0];
但保证它在所有编译器中都能工作的方法是:

uint32 words[1];
然后,无论如何声明,您都可以为对象分配:

Bitmapset *allocate(int n)
{
    Bitmapset *p = malloc(offsetof(Bitmapset, words) + n * sizeof(p->words[0]));
    p->nwords = n;
    return p;
}

虽然为了获得最佳结果,您应该使用
size\u t
而不是
int

,但这通常是为了允许对可变大小的结构实例进行惯用访问。考虑到您的示例,在运行时,您可能会在内存中设置一个位图集,如下所示:

-----------------
| nwords   |  3 |
| words[0] | 10 |
| words[1] | 20 |
| words[2] | 30 |
-----------------
因此,运行时变量uint32“挂起”在结构的末尾,但可以访问,就好像它们是在结构中内联定义的一样。这基本上是(ab)使用C不进行运行时数组边界检查的事实来编写代码,如:

for (int i = 0; i < myset.nwords; i++) {
  printf("%d\n", myset.words[i]);
}
for(int i=0;i
谢谢。那么,如果传递的n是一个奇数,那么这种复杂的分配对于结构填充会有问题吗?@Oxdeadbeef-是的,我想。您不会在连续内存中真正存储它们的数组。如果你想要一个数组,你最好使用
Bitmapset*a[20]={NULL}
位图集**a=malloc(20*sizeof*a)
。语法
offsetof(位图集,words[n])
是一个扩展(大多数编译器恰好支持该扩展)。为了严格遵守,请使用
offsetof(Bitmapset,words)+n*sizeof(p->words[0])
@Jed-我不知道这一点,尽管我应该猜到。修复。@ChrisLutz:标准中是否有任何内容禁止编译器将
p->words[i]
优化为
p->words[0]
,因为前者仅在数组元素存在分配内存且下标小于数组大小(即为零)的情况下定义行为?我怀疑,如果数组是间接访问结构中的最后一项,即使是通常可能优化单项数组访问的编译器也会避免这样做,但标准中是否有任何东西会禁止它(或者证明代码假设编译器不会这样做)?不会以同样的方式工作。如果您这样做,那么words[2]会说“跟随位于结构的'words'字段中的指针,然后再前进2*8==16字节并访问那里的内存。”您必须(例如)malloc()一个单独的内存区域来包含堆中的words数组,这可能会影响性能和易用性。
for (int i = 0; i < myset.nwords; i++) {
  printf("%d\n", myset.words[i]);
}