C语言中的零长度数组使用说明

C语言中的零长度数组用法详解

在C语言中允许在结构体和联合体中定义零长度的数组,写法可以是以下两种:

char p[]或者char p[0],这个数组定义在结构体或者联合体中,不占用空间大小。

这是个广泛使用的常见技巧,常用来构成缓冲区。比起指针,用空数组有这样的优势:

1.不需要初始化,数组名直接就是所在的偏移;

2.不占任何空间,指针需要占用int长度空间,空数组不占任何空间。

“这个数组不占用任何内存”,意味着这样的结构节省空间;“该数组的内存地址就和他后面的元素的地址相同”,意味着无需初始化,数组名就是后面元素的地址,直接就能当做指针使用。

这样的写法最适合制作动态buffer。因为可以这样分配空间:

malloc(sizeof(struct  XXX)+  buff_len);

看出来好处没有?直接就把buffer的结构体和缓冲区一块分配了。用起来也非常方便,因为现在kongsuzu其实变成了buff_len长度的数组了。

这样的好处有两点:

一次分配解决问题,省了不少麻烦。大家知道为了防止内存泄漏,如果是分两次分配(结构体和缓冲区),那么要是第二次malloc失败了,必须回滚释放第一个分配的结构体。这样带来了编码麻烦。其次,分配了第二个缓冲区以后,如果结构里面用的是指针,还要为这个指针赋值。同样,在free这个buffer的时候,用指针也要两次free。如果用空数组,所有问题一次解决。

其次,大家知道小内存的管理是非常困难的,如果用指针,这个malloc分配出来的空间中的struct部分就是小内存了,在系统内存在多了势必严重影响内存管理的性能。要是用空数组把struct和实际数据缓冲区一次分配大块问题,就没有这个问题。

即使零长度数组的优点如此之多,但是使用的时候也是要倍加小心:

1.零长度数组不是所有的c标准都支持,gnu c支持,ANSI C不支持,C++不支持。

2.如果某种情况下出现了这个结构体中只有零长度数组一个元素,这个可能会就会导致错误降临。

3.零长度数组需要放于结构体的结尾处。

时间: 2024-12-25 16:45:07

C语言中的零长度数组使用说明的相关文章

GNU C中的零长度数组(转载)

GNU C中的零长度数组(转载) 原文链接:http://blog.csdn.net/ssdsafsdsd/article/details/8234736 在标准C和C++中,长度为0的数组是被禁止使用的.不过在GNU C中,存在一个非常奇怪的用法,那就是长度为0的数组,比如Array[0];很多人可能觉得不可思议,长度为0的数组是没有什么意义的,不过在这儿,它表示的完全是另外的一层意思,这个特性是不可移植的,所以,如果你致力于编写可移植,或者是稍稍需要跨平台的代码,这些Trick最好还是收起来

零长度数组意义

在_C++ Primer_动态数组中提到:动态分配一个空数组是合法的. size_t n = get_size(); int* p = new int[n]; for(int* q = p; q != p + n; ++q) char arr[0];//错误 char cp = new char[0]; 当我们用new分配一个大小为0的数组时,new返回一个合法的非空指针.此指针保证与new返回的其他任何指针不相同,对于零长度的数组来说,此指针就像尾后指针一样.我们可以像尾后迭代器一样使用这个指

Java中应该返回零长度数组或空集合,而不是返回null(转)

说明:为了避免在数组和集合的获取上增加null的判断,同时也能减少不必要的空指针异常,通常会在业务返回零数组或空集合. 方法: 1.数组: 定义全局静态常量来减少内存开销:private static final int EMPTY_ARRAY = new int[0];,当然,也可以直接局部变量等等. 2.集合: 使用工具类Collections的emptyList()进行放回. 参考: http://blog.csdn.net/tounaobun/article/details/850216

r语言中如何进行两组独立样本秩和检验

安装所需的包 wants <- c("coin") has <- wants %in% rownames(installed.packages()) if(any(!has)) install.packages(wants[!has])> 一个样本 测试 set.seed(123) medH0 <- 30 DV <- sample(0:100, 20, replace=TRUE) DV <- DV[DV != medH0] N <- lengt

零长度数组的妙用

零长度是指定义数组时,指定其长度为0(如int arr[0];),这样的数组不占用实际的空间,但能通过数组名访问到其指向的地址.如下例所示: #include <stdlib.h> #include <stdio.h> struct device { int num; int count; int reserve[0]; /* * reserve是一个数组名:该数组没有元素:该数组的其实地址紧随结构体device之 * 后:这种声明方法可以巧妙的实现C语言里的数组扩展,比将reve

C语言中的函数、数组与指针

1.函数:当程序很小的时候,我们可以使用一个main函数就能搞定,但当程序变大的时候,就超出了人的大脑承受范围,逻辑不清了,这时候就需要把一个大程序分成许多小的模块来组织,于是就出现了函数概念:  函数是C语言代码的基本组成部分,它是一个小的模块,整个程序由很多个功能独立的模块(函数)组成.这就是程序设计的基本分化方法: (1) 写一个函数的关键: 函数定义:函数的定义是这个函数的实现,函数定义中包含了函数体,函数体中的代码段决定了这个函数的功能: 函数声明:函数声明也称函数原型声明,函数的原型

C语言中关于指针的学习

指针是C语言中广泛使用的一种数据类型. 运用指针编程是C语言最主要的风格之一.利用指针变量可以表示各种数据结构: 能很方便地使用数组和字符串: 并能象汇编语言一样处理内存地址,从而编出精练而高效的程序.指针极大地丰富了C语言的功能. 学习指针是学习C语言中最重要的一环, 能否正确理解和使用指针是我们是否掌握C语言的一个标志.同时, 指针也是C语言中最为困难的一部分,在学习中除了要正确理解基本概念,还必须要多编程,上机调试.只要作到这些,指针也是不难掌握的. 指针的基本概念 在计算机中,所有的数据

从头开始-05.C语言中函数

函数: 完成特定功能代码段 特点:函数只有调用的时候才会执行 定义格式:返回值类型 函数名称(形参类型 形参名称,...){ 语句; ...  } 函数参数 形式参数:在定义函数的时候,函数名后面小括号中的参数 实际参数:在函数调用的时候,函数名后面小括号中的参数 注意点: 形参与实参必须一一对应 实参与形参的类型必须一致 基本数据类型作为函数参数传递是值传递 组作为函数参数传递是地址传递 指针作为函数参数传递是地址传递 结构体作为函数参数传递是值传递 返回值: return 作用: 1.结束函

C语言中位域操作

C语言中位域定义: 以结构体中定义申明变量的形式: 类型说明符 位域名:位域宽度 struct bit{ int a:4; // 申明位域变量a,占用4个bit位宽度 int b:4; // 申明位域变量b,占用4个bit位宽度 int c:4; // 申明位域变量c,占用4个bit位宽度 }; 在gcc编译器中对结构体进行了默认的对齐操作,以下的所有的现象都是基于gcc的编译条 件:1):申明的两个相连的位域变量占位一般都是紧密连接的,例如上面的a和b,或者是b和 c:a占用起始字节的低4位,