C语言的变长数组

这篇具有很好参考价值的文章主要介绍了C语言的变长数组。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

问题背景

写程序的时候经常要定义这样一个数组,要前面程序运行后才能知道要定义数组的大小。

C99之可变长度数组(VLA)

C99:
1994年,由ANSI/ISO联合委员会开始修订C标准
1999年,1994年对C语言的修订引出了ISO 9899:1999的发表,它通常被称为C99
C11:
2011年,国际标准化组织(ISO)和国际电工委员会(IEC) 旗下的C语言标准委员会(ISO/IEC JTC1/SC22/WG14)正式发布了C11标准

c99标准中,新增了可变长度数组:Variable-length array (VLA);C11中VLA变为可选项,不是语言必备的特性。

关于变长数组

变长数组中的“变”不是指可以修改已创建数组的大小,一旦创建了变长数组,它的大小则保持不变。这里的“变”指的是:在创建数组时,可以使用变量指定数组的长度。(普通数组只能用常量或常量表达式指定数组的长度)

  1. 变长数组VLA只能是局部变量数组
  2. 变长数组VLA不能在定义的时候进行初始化
  3. 变长数组VLA必须是自动存储类别,即不能使用extern或static存储类别说明符
  4. 变长数组VLA不等于动态数组,本质还是静态数组,也就是说,数组的长度在变量的整个生命周期中是不可变的
  5. 由于变长数组只能是局部变量,且必须是自动存储类别,因此变长数组分配在栈上
  6. 可变长数组对于多维数组也适用(如array[a][b] )

示例:

#include <stdio.h>

int main(void)
{
	int a=0;
	int b=0;
	scanf("%d %d",&a,&b);
	char array[a][b];
	printf("sizeof(array)=%d\n",sizeof(array));
	return 0;
}

上述代码需在支持C99标准的编译器上才行(注意,VS系列编译器均不支持该特性)

我编译成功用的gcc版本号:
c语言变长数组,C语言,c语言,算法,开发语言
c语言变长数组,C语言,c语言,算法,开发语言
根据上面关于数组的几项注意点,下面列出几种错误的示例:

int a=2;
int b=3;
char array1[a][b] = {1,2,3,4,5,6}; //错误,变长数组VLA不能在定义的时候进行初始化
char array2[a][b] = {{1,2,3},{4,5,6}}; //错误,变长数组VLA不能在定义的时候进行初始化
static char array3[a][b]; //错误,变长数组VLA必须是自动存储类别

关于如果是const变量做数组长度,下面还有几种情况需要思考:
1、在函数体外部,全局数组长度用const类型全局变量,是否可行? – 答:可以。

#include <stdio.h>
const int len = 10;
char array[len];
void main()
{
	printf("sizeof(array)=%d\n",sizeof(array));
}

2、在函数体外部,static 全局数组长度用const类型全局变量,是否可行? – 答:可以。

#include <stdio.h>
const int len = 10;
static char array[len];
void main()
{
	printf("sizeof(array)=%d\n",sizeof(array));
}

3、在函数体内部,static 局部数组长度用const类型局部变量,是否可行? – 答:可以。

#include <stdio.h>

void main()
{
	const int len = 10;
	static char array[len];
	printf("sizeof(array)=%d\n",sizeof(array));
}

4、在函数体内部,局部数组长度用const类型局部变量,是否可行? – 答:可以。

#include <stdio.h>

void main()
{
	const int len = 10;
	char array[len];
	printf("sizeof(array)=%d\n",sizeof(array));
}

总结:const变量不能直接改变,用其定义数组长度实际上已经不再是变长数组了。

动态内存分配malloc实现动态数组

C语言里,所有变量空间都是在程序运行之初向系统申请的,包括指针,除了一些动态申请方式如malloc函数。没有申请的空间系统是不允许读写的。在C99标准之前的C89,C90,如果一个数组大小是变量定义,则在程序运行前不能确定数组大小,也就无法申请,故不允许。所以,解决的办法便是通过malloc函数,即

int a[n];

可改为

int* const a = (int*)malloc(sizeof(int)*n);

这样a变量就完全可以当作一个数组直接使用了,包括a[1]之类的。因为“[]”中括号运算符做的只是偏移其内的地址数并取值。如:

a[1]

等价于

*(a + 1)

而const修饰符在星号之后,则表示指针在被声明后指向内容可以变,指向地点不能变,即只能指向这个获取的空间,完全符合数组的性质
const可以去掉,但要保证使用时不改变a的指向。

const是一个C语言(ANSI C)的关键字,具有着举足轻重的地位。它限定一个变量不允许被改变,产生静态作用。使用const在一定程度上可以提高程序的安全性和可靠性。

malloc实现一维动态数组p[m]

示例:

#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
int main(void)
{
    int m;
    scanf("%d", &m);
    int* const p = (int*)malloc(m*(sizeof(int)));
    memset(p, 0, m);//初始化,每个元素都为零
    int i;
    for (i=0;i<m; i++)//数组赋值
    {
        p[i] = i;
    }
    for (i = 0; i <m; i++)//打印数组
    {
        printf("%d,", p[i]);
    }
    free(p);
    return 0;
}

malloc实现二维动态数组p[m][n]

示例:

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
int main(void)
{
    int m, n;
    scanf("%d %d", &m,&n);
    int **p;
    p = (int**)malloc(m*(sizeof(int*)));//二级指针所在地址申请内存
    int i, j;
    for (i = 0; i<m; i++)
        p[i] = (int*)malloc(sizeof(int)*n);//一级指针所在地址申请内存
    for (i = 0; i < m; i++)
        for (j = 0; j < n; j++)
            p[i][j] = i + j;
    for (i = 0; i < m; i++)
    {
        for (j = 0; j < n; j++)
        {
            printf("%d %p   ", p[i][j], &p[i][j]);     //输出每个元素及地址,每行的列与列之间的地址时连续的,行与行之间的地址不连续  
        }
        printf("\n");
    }
    for (i = 0; i < m; i++) free(p[i]);     
    free(p);
    return 0;
}

测试示例:
c语言变长数组,C语言,c语言,算法,开发语言

变长数组VLA对比动态内存分配malloc

变长数组是自动存储类型。因此,程序在离开变长数组定义所在的块、函数时,变长数组占用的内存空间会被自动释放,不必使用free()。另一方面,用malloc()创建的数组不必局限在一个函数内访问。

变长数组内存分配是在栈上,使用malloc内存分配在堆上。

0长度数组实现可变长数组

详见另一篇博文:https://blog.csdn.net/weixin_44788542/article/details/125858372文章来源地址https://www.toymoban.com/news/detail-624432.html

到了这里,关于C语言的变长数组的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C语言算法笔记1:结构体、结构体数组实战讲解

    今日开始为电赛复习一些必备的算法知识,本文回顾复习结构体的概念以及一些基本操作,每个知识点都有代码实践演示,可以复制测试查看! 目录 前言——往日的困惑: 一、结构体基础知识与用途: C语言结构体是一种自定义数据类型: 结构体可以包含不同的数据类型:

    2024年02月12日
    浏览(42)
  • 头歌(C语言)-数据结构与算法-数组(共7关)

    任务描述 本关任务:将十个数进行从大到小的顺序进行排列。 相关知识(略) 编程要求 根据提示,在右侧编辑器 Begin-End 处补充代码。 输入 输入十个整数。 输出 以从大到小的顺序输出这个十个数。 测试说明 样例输入: 1 2 3 4 5 6 7 8 9 10 样例输出: 10 9 8 7 6 5 4 3 2 1 代码:

    2024年02月11日
    浏览(42)
  • 数据结构与算法教程,数据结构C语言版教程!(第五部分、数组和广义表详解)五

    数组和广义表,都用于存储逻辑关系为“一对一”的数据。 数组存储结构,99% 的编程语言都包含的存储结构,用于存储不可再分的单一数据;而广义表不同,它还可以存储子广义表。 本章重点从矩阵的角度讨论二维数组的存储,同时讲解广义表的存储结构以及有关其广度和

    2024年01月23日
    浏览(50)
  • C语言数据结构+KMP算法next数组优化计算方法+优化后子串匹配代码实现

    通过我之前那篇KMP算法的讲解,我们可以快速手算KMP算法的next数组,但是之前计算的next数组在一些情况下会有缺陷,比如模式串’aaaab’和主串’aaabaaaab’进行匹配 令模式串指针为j 当第一个元素不匹配时,下一次匹配还是要从模式串的第一个元素与主串匹配,其实我们可以直接写

    2024年02月06日
    浏览(54)
  • 数据结构与算法教程,数据结构C语言版教程!(第五部分、数组和广义表详解)三

    数组和广义表,都用于存储逻辑关系为“一对一”的数据。 数组存储结构,99% 的编程语言都包含的存储结构,用于存储不可再分的单一数据;而广义表不同,它还可以存储子广义表。 本章重点从矩阵的角度讨论二维数组的存储,同时讲解广义表的存储结构以及有关其广度和

    2024年01月21日
    浏览(48)
  • 初阶算法(3):二分法的讲解与实现(C语言),以及二分不止光在有序数组中的应用

     第一章 初阶算法(1):通过简单的排序算法来认识时间复杂度  第二章 初阶算法(2):进行详细地介绍插入排序的细节和时间复杂度  第三章 初阶算法(3):二分法的讲解与实现,以及二分不止光在有序数组中的应用 目录 系列文章目录 前言 一、二分法的讲解与实现

    2024年02月14日
    浏览(44)
  • 类厂,变长参数,序列化

    在记录nav2中的各类信息,保存到文件中,以便后面回放来分析算法的编程中发现。 各种信息记录的数据不同,可能还会有变化,所以决定采用类厂模式,参见C++设计模式入门 有个信息记录的基类,不同的记录对应不同的子类。 目前的信息类型,后面估计要有扩展,用类扩展

    2024年01月21日
    浏览(34)
  • C语言深度剖析,关于查找一个数组里面的最大值(max)、最小值(min)的通俗算法,简单易懂。采用比较法进行查找。

    这里采用了一个假设 假设第一个数为最大值,其他数与第一个数比较。 这个算法与上面求解最大值的方法相反。 1、首先,定义行和列。 用行标记来确定列的数量。 i 来表示行, j来表示列。 2、内嵌的for循环只打印一行所有列。 如,i=3时,此时j=3. 从1*3 遍历到3*3后内嵌循环

    2024年02月08日
    浏览(46)
  • 【机器学习】 贝叶斯理论的变分推理

    许志永         贝叶斯原理,站在概率角度上似乎容易解释,但站在函数立场上就不那么容易了;然而,在高端数学模型中,必须要在函数和集合立场上有一套完整的概念,其迭代和运算才能有坚定的理论基础。          贝叶斯定理看起来天真地简单。但是,分母是在

    2024年02月13日
    浏览(54)
  • 迁移学习:互信息的变分上下界

    在机器学习,尤其是涉及异构数据的迁移学习/联邦学习中,我们常常会涉及互信息相关的优化项,我研一下期的处女作(发在SDM\\\'24上)也是致力于此(ArXiv论文链接:FedDCSR,GitHub源码链接:FedDCSR)。其思想虽然简单,但其具体的估计与优化手段而言却大有门道,我们今天来

    2024年02月08日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包