dsp*_*pjm 7 c linux compiler-construction gcc
据说零长度数组用于可变长度结构,我可以理解.但令我困惑的是为什么我们不仅仅使用指针,我们可以取消引用并以相同的方式分配不同的大小结构.
编辑 - 添加评论示例
假设:
struct p
{
char ch;
int *arr;
};
Run Code Online (Sandbox Code Playgroud)
我们可以用这个:
struct p *p = malloc(sizeof(*p) + (sizeof(int) * n));
p->arr = (struct p*)(p + 1);
Run Code Online (Sandbox Code Playgroud)
获得一块连续的记忆.但是,我似乎忘记了空间p->arr占用,它似乎是零大小数组方法的不同之处.
das*_*ght 13
如果使用指针,则结构将不再具有可变长度:它将具有固定长度,但其数据将存储在不同的位置.
零长度数组*背后的想法是将数组的数据"与行"存储在结构中的其余数据中,以便数组的数据跟随结构在内存中的数据.指向单独分配的内存区域的指针不允许您这样做.
element_type flexArray[]而不是element_type flexArray[0],即你掉落零.
指针并不是真正需要的,因此它没有任何好处而占用空间.此外,它可能意味着另一层次的间接,这也不是真正需要的.
比较这些示例声明,对于动态整数数组:
typedef struct {
size_t length;
int data[0];
} IntArray1;
Run Code Online (Sandbox Code Playgroud)
和:
typedef struct {
size_t length;
int *data;
} IntArray2;
Run Code Online (Sandbox Code Playgroud)
基本上,指针表示"数组的第一个元素位于此地址,可以是任何",它比通常需要的更通用.所需的模型是"数组的第一个元素就在这里,但我不知道数组有多大".
当然,第二种形式可以使阵列增长而不会冒"基本"地址(IntArray2结构本身的地址)发生变化的风险,这可能非常简洁.你不能这样做IntArray1,因为你需要将基本结构和整数数据元素分配在一起.权衡,权衡......
这些是所谓的"struct hack"的各种形式,在comp.lang.c FAQ的问题2.6中讨论过.
定义大小为0的数组在C中实际上是非法的,并且至少自1989 ANSI标准以来.有些编译器允许它作为扩展,但依赖于它会导致不可移植的代码.
实现此目的的更便携方式是使用长度为1的数组,例如:
struct foo {
size_t len;
char str[1];
};
Run Code Online (Sandbox Code Playgroud)
您可以分配多个sizeof (struct foo)字节,len用于跟踪分配的大小,然后访问str[N]以获取数组的第N个元素.由于C编译器通常不进行数组边界检查,因此这通常会"起作用".但是,严格来说,这种行为是不确定的.
1999 ISO标准增加了一个名为"灵活阵列成员"的功能,旨在取代这种用法:
struct foo {
size_t len;
char str[];
};
Run Code Online (Sandbox Code Playgroud)
您可以像旧的struct hack一样处理这些问题,但行为定义明确.但你必须自己做所有的簿记; sizeof (struct foo)例如,仍然不包括数组的大小.
当然,您可以使用指针代替:
struct bar {
size_t len;
char *ptr;
};
Run Code Online (Sandbox Code Playgroud)
这是一个非常好的方法,但它有不同的语义."struct hack"或灵活数组成员的主要优点是数组与结构的其余部分连续分配,您可以使用结构复制数组memcpy(只要目标已正确使用)分配).使用指针,数组将单独分配 - 这可能是您想要的,也可能不是.
| 归档时间: |
|
| 查看次数: |
1957 次 |
| 最近记录: |