【C语言】变长数组与柔性数组
2016-05-11 17:34
330 查看
百度百科中这样定义变长数组:
C语言中,直到C99标准出现之前,声明数组时在方括号内只能使用整数常量表达式。而C99做了很大改进,允许数组的[ ]中的值是整形变量或是整形表达式。这就解释了下面的情况:
int n;
scanf ("%d", &n);
int array
;
虽然n确实是需要运行时动态确定的变量,但是在C99中,以这种变量作为数组大小的形式已经是允许的了。这样的数组就被称之为“变长数组”。
注意:变长数组是指用整型变量或表达式声明或定义的数组,而不是说数组的长度会随时变化,变长数组在其生存期内的长度同样是固定的。
以下内容转自:
/article/5122619.html
前两天看程序,发现在某个函数中有下面这段程序:
gcc 去编译这段程序,发现确实没报错,而且我对此数组进行一些操作,结果也都是正确!这简直颠覆了我的知识框架!难道大学老师教我的、我平时看的书,都是错误的吗?!我开始寻找答案...
在 ISO/IEC9899 标准的 6.7.5.2
Array declarators 中明确说明了数组的长度可以为变量的,称为变长数组(VLA,variable length array)。(注:这里的变长指的是数组的长度是在运行时才能决定,但一旦决定在数组的生命周期内就不会再变。)
在 GCC 标准规范的 6.19 Arrays
of Variable Length 中指出,作为编译器扩展,GCC 在 C90 模式和 C++ 编译器下遵守 ISO C99 关于变长数组的规范。
这下,终于安心了,原来这种语法确实是 C 语言规范,GCC 非常完美的支持了 ISO C99。但令人遗憾的是,我们的大学老师教给我们的还是老一套,虽然关系不是很大,但这也从侧面反映了我们的教育是多么地滞后!而且我们读的 C 语言书,在不加任何限定的条件下,就说某某语法是不对的,读书的人只能很痛苦地记下!小小吐槽一下,下面继续...
这种变长数组有什么好处呢?你可以使用
函数用来在栈上分配空间,当函数返回时自动释放,无需手动再去释放;VLA 就不一样了,在数组名生命周期结束之后,所分配的空间也就随之释放。
从上例就可以看出,零长数组在有固定头部的可变对象上非常适用,我们可以根据对象的大小动态地去分配结构体的大小。
在 Linux 内核中也有这种应用,例如由于 PID 命名空间的存在,每个进程 PID 需要映射到所有能看到其的命名空间上,但该进程所在的命名空间在开始并不确定(但至少为
init 命名空间),需要在运行是根据 level 的值来确定,所以在该结构体后面增加了一个长度为 1 的数组(因为至少在一个init命名空间上),使得该结构体 pid 是个可变长的结构体,在运行时根据进程所处的命名空间的 level 来决定 numbers 分配多大。(注:虽然不是零长度的数组,但用法是一样的)
C语言中,直到C99标准出现之前,声明数组时在方括号内只能使用整数常量表达式。而C99做了很大改进,允许数组的[ ]中的值是整形变量或是整形表达式。这就解释了下面的情况:
int n;
scanf ("%d", &n);
int array
;
虽然n确实是需要运行时动态确定的变量,但是在C99中,以这种变量作为数组大小的形式已经是允许的了。这样的数组就被称之为“变长数组”。
注意:变长数组是指用整型变量或表达式声明或定义的数组,而不是说数组的长度会随时变化,变长数组在其生存期内的长度同样是固定的。
以下内容转自:
/article/5122619.html
前两天看程序,发现在某个函数中有下面这段程序:
int n; //define a variable n int array ; //define an array with length n在我所学的C语言知识中,这种数组的定义在编译时就应该有问题的,因为定义数组时,数组的长度必须要是一个大于0的整型字面值或定义为 const 的常量。例如下面这样
int array1[10]; //valid int const N = 10; int array2 ; //valid int n = 10; int array3 ; //invalid但从上面看第三种定义数组的方法也是正确的,于是,我用
gcc 去编译这段程序,发现确实没报错,而且我对此数组进行一些操作,结果也都是正确!这简直颠覆了我的知识框架!难道大学老师教我的、我平时看的书,都是错误的吗?!我开始寻找答案...
C 语言中变长数组
最官方的解释应该是 C 语言的规范和编译器的规范说明了。在 ISO/IEC9899 标准的 6.7.5.2
Array declarators 中明确说明了数组的长度可以为变量的,称为变长数组(VLA,variable length array)。(注:这里的变长指的是数组的长度是在运行时才能决定,但一旦决定在数组的生命周期内就不会再变。)
在 GCC 标准规范的 6.19 Arrays
of Variable Length 中指出,作为编译器扩展,GCC 在 C90 模式和 C++ 编译器下遵守 ISO C99 关于变长数组的规范。
这下,终于安心了,原来这种语法确实是 C 语言规范,GCC 非常完美的支持了 ISO C99。但令人遗憾的是,我们的大学老师教给我们的还是老一套,虽然关系不是很大,但这也从侧面反映了我们的教育是多么地滞后!而且我们读的 C 语言书,在不加任何限定的条件下,就说某某语法是不对的,读书的人只能很痛苦地记下!小小吐槽一下,下面继续...
这种变长数组有什么好处呢?你可以使用
alloca函数达到类似的动态分配数组的效果, alloca
函数用来在栈上分配空间,当函数返回时自动释放,无需手动再去释放;VLA 就不一样了,在数组名生命周期结束之后,所分配的空间也就随之释放。
零长数组
GCC 中允许使用零长数组,把它作为结构体的最后一个元素非常有用,struct line { int length; char contents[0]; }; struct line *thisline = (struct line *) malloc (sizeof (struct line) + this_length); thisline->length = this_length;
从上例就可以看出,零长数组在有固定头部的可变对象上非常适用,我们可以根据对象的大小动态地去分配结构体的大小。
在 Linux 内核中也有这种应用,例如由于 PID 命名空间的存在,每个进程 PID 需要映射到所有能看到其的命名空间上,但该进程所在的命名空间在开始并不确定(但至少为
init 命名空间),需要在运行是根据 level 的值来确定,所以在该结构体后面增加了一个长度为 1 的数组(因为至少在一个init命名空间上),使得该结构体 pid 是个可变长的结构体,在运行时根据进程所处的命名空间的 level 来决定 numbers 分配多大。(注:虽然不是零长度的数组,但用法是一样的)
struct pid { atomic_t count; unsigned int level; /* lists of tasks that use this pid */ struct hlist_head tasks[PIDTYPE_MAX]; struct rcu_head rcu; struct upid numbers[1]; };
相关文章推荐
- C语言 字符串二维数据的引用
- C语言编程的进制问题问题
- C++队列中应该注意的一些问题
- c++ find 函数
- 【C语言】判断字符串是否是回文
- C++ vector 的简单用法
- c++第五次实验--多继承
- more effective C++的读书笔记 ——不要重载&&和||
- 【C语言】动态内存分配alloca
- C++之嵌套类与外围类及友元
- C++中的::操作符
- 关于C++全局变量声明的问题
- c++第五次上机实验——教师干部类
- C++实现双链表
- C++实现双链表
- C++实现双链表
- 基于C语言EOF与getchar()的使用详解
- 第7周 C语言程序设计(新2版) 练习1-13 打印输入单词长度的直方图(水平与垂直)
- 栈的测试--四则运算表达式求值(C语言)
- C++程序设计语言练习5.1