浅析长度为0的数组

前面在看Xen的源码时,遇到了一段代码,如下所示:

注意上面最后一行的代码,这里定义了一个长度为的数组,这种用法可以吗?为什么可以使用长度为的数组?长度为的数组到底怎么使用?……这篇文章主要针对该问题进行简单的讲解。废话不多说了,现在就开始。

长度为的数组在标准cc++中是不允许的,如果使用长度为的数组,编译时会产生错误,提示数组长度不能为。但在GNUc中,这种用法却是合法的。它的最典型的用法就是位于数组中的最后一项,如上面所示,这样做主要是为了方便内存缓冲区的管理。如果你将上面的长度为的数组换为指针,那么在分配内存时,需采用两步:首先,需为结构体分配一块内存空间;其次再为结构体中的成员变量分配内存空间。这样两次分配的内存是不连续的,需要分别对其进行管理。当使用长度为的数组时,则是采用一次分配的原则,一次性将所需的内存全部分配给它。相反,释放时也是一样的。

对于长度为的数组,在gcc手册中,有如下一段代码片段:

struct line {

int length;

char contents[0];

};

struct line *thisline = (struct line *)malloc (sizeof (struct line) + this_length);

thisline->length = this_length;

这段代码的主要含义是定义了一个结构体,并对其进行初始化,上面结构体的第二个成员变量contents[0]事实上是不占内存空间的,因此整个结构体的长度sizeof(struct line)4。当采用malloc为其申请内存空间时,如上所示,申请了一段长度为结构体长度加可变长度的内存空间给结构体类型的指针,这时contents就指向申请的可变长度的内存空间。由于是一次申请的,所以这段可变长度的内存空间和前面的结构体长度的内存空间是连续的。对于这段可变长度的内存空间,可以采用数组的方式对其进行访问。对于整个结构体,当不再使用时,可以使用free函数一次性对其进行释放,而不必像指针那样分别释放。

下面举例进行说明:

#include <stdio.h>
#include <stdlib.h>
#define LENGTH 10

struct test1
{
int a;
int *b;
}__attribute((packed));

struct test2
{
int a;
int b[0];
}__attribute((packed));

struct test3
{
int a;
int b[1];
}__attribute((packed));

int main()
{
struct test1 *var1;
struct test2 *var2;
struct test3 *var3;
int i;

printf("the length of struct test1:%d\n",sizeof(struct test1));
printf("the length of struct test2:%d\n",sizeof(struct test2));
printf("the length of struct test3:%d\n",sizeof(struct test3));

var1=(struct test1*)malloc(sizeof(struct test1));
var1->a=1;
var1->b=(int *)malloc(sizeof(int));
*var1->b=1;
printf("\nvar1->a=%d,*(var1->b)=%d\n",var1->a,*var1->b);

var2=(struct test2*)malloc(sizeof(struct test2)+sizeof(int)*LENGTH);
var2->a=2;
printf("\nvar2->a=%d\n",var2->a);
for(i=0;i<LENGTH;i++)
{
var2->b[i]=i;
printf("var2->b[i]=%d\t",var2->b[i]);
}
printf("\n\n"); 

var3=(struct test3*)malloc(sizeof(struct test3));
var3->a=3;
(var3->b)[0]=3;
printf("var3->a=%d,(var3->b)[0]=%d\n",var3->a,(var3->b)[0]);


free(var1->b);
free(var1);
free(var2);
free(var3);

}

这段程序的运行结果如下图所示:

从上面的结果可以看出:

长度为的数组并不占有内存空间,而指针方式需要占用内存空间。

对于长度为数组,在申请内存空间时,采用一次性分配的原则进行;对于包含指针的结构体,才申请空间时需分别进行,释放时也需分别释放。

对于长度为的数组的访问可采用数组方式进行。

转载于:https://my.oschina.net/u/176416/blog/33054

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Vue,可以使用v-for指令来进行循环遍历数组。 以下是一个示例代码,展示了如何使用v-for遍历数组并输出每个数组元素: <ul> <li v-for="item in names">{{ item }}</li> </ul> 其,names是一个数组,item是遍历过程每个数组元素的值。在上述代码,通过v-for指令将数组names的每个元素渲染为一个li标签,并输出元素的值。 如果你还需要获取数组元素的下标,可以使用以下的语法: <ul> <li v-for="(item, index) in names">{{ index + 1 }}. {{ item }}</li> </ul> 其,index表示当前元素的下标,item表示当前元素的值。在上述代码,通过v-for指令将数组names的每个元素渲染为一个li标签,并输出下标值和元素的值。 通过使用v-for指令,你可以方便地在Vue数组进行循环遍历,并灵活地输出数组元素的值或下标。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [浅析vue常见循环遍历指令的使用 v-for](https://download.csdn.net/download/weixin_38500222/12957661)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Vue:循环遍历(v-for)](https://blog.csdn.net/yufengguanyun/article/details/123297502)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值