C语言之数组,一维数组、二维数组以及变长数组的语法以及用法详细笔记



前言

本文将详细介绍C语言中数组的语法,数组初始化注意事项,数组在内存中是如何存储的、二维数组的特点,变长数组的使用以及sizeof和strlen如何计算数组的长度,希望对大家有所帮助,我使用的IDE为vs2022,话不多说,直接上干货。


一、数组的概念

数组是一组相同类型元素的集合;

  • 数组里存放的是一个或多个相同类型的数据,因此数组元素个数不能为0
  • 数组分为一维数组和多维数组,多维数组一般比较常见的就是二维数组

所以,在我们需要存储多个相同类型的数据时,我们就会使用数组来进行存储和使用

下面我们开始介绍一维数组


二、一维数组

1.语法

创建一维数组的语法如下:

type  arr_name[常量值];

  • type  指定的是数组中存放的数据的类型,比如 int整形,char字符型,float、double等等,也可以是自定义的类型。
  • arr_name指定的是数组的名字,和变量名一样,名字可根据实际情况取有意义的名字即可。
  • [ ]中的常量值是指定数组的大小的,也就是数组元素的个数。


2.一维数组的初始化

概念:我们在创建数组的时候对数组进行赋值就叫做初始化。

初始化又分为完全初始化和不完全初始化(以整形数组为例)

  1. 完全初始化:即数组有多少元素就初始化多少元素
  2. 不完全初始化:初始化一部分元素

注意:不完全初始化时,值会按顺序赋给数组,而其余元素则为0

另外:在初始化数组时可以可以省略[ ]里的常量值,系统会根据所赋值的元素个数,自动分配大小

如:

系统会给arr分配6个整形空间

注意:只有初始化了才能省略[ ]中的值,不初始化将会报错


3.数组的下标引用

即数组的每一个元素都对应有一个下标

如:

创建一个整形变量

int arr [10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

元素下标:    0  1  2  3  4  5  6  7  8  9 

即元素下标从0开始,对应的是数组的第一个元素,也就是上面的1,然后依次往后对应

最后一个元素下标即为元素个数减一,也就是上面的10-1等于9,最后一个元素下标为9

而下标引用的语法为:

数组名[元素下标]

即可找出对应的元素,然后可以对其进行赋值、修改或者打印等等操作

如:


4.数组的类型

我们都知道,C语言中,我们在定义变量时会定义它的类型,比如 int a = 10, 这里变量a的类型为整形,那么数组有没有类型呢?

虽然如 int arr[10] 数组前面有个 int ,但这个指的是数组内部的元素类型,而不是数组类型。

其实,数组也是有类型的,数组算是⼀种自定义类型,去掉数组名留下的就是数组的类型。

我们可以通过调试看到数组类型

如:

即去掉数组名留下的就是数组类型


5.数组的输入

因为数组有多个元素,例如整形数组,如果使用scanf函数输入就需要多个%d,会非常麻烦,所以对于多个元素的输入,我们一般采用for循环输入。

我们以整形数组,和字符型数组两组演示

1.整形数组:

通过监视窗口我们发现数组被成功赋值

注意:输入时每个元素之间空格隔开

2.字符型数组:

字符型数组与其他数组稍有不同,因为字符型数组有两种输入方式

 1.%c输入

通过监视窗口我们发现数组被成功赋值

注意:%c输入时,元素之间不留空格,如需留空格,可在%c后面加个空格

2.%s输入

我们发现也能成功赋值

注意:%s输入,元素之间不能有空格,会导致元素读取不全

另外:字符串输入末尾会带一个\0元素

如:

我们能清楚的发现ch2比ch1多一个元素,也就是\0


6.数组的输出打印

同输入一样,数组的输出打印我们一般也是使用循环来打印

如下:


7.一维数组在内存中的存储

为了更深入地了解数组,我们最好能了解数组在内存中的存储

我们可以依次打印数组元素的地址来观察:(为了方便观察,我们在32位系统上打印)

  • 很明显,我们发现,每个地址之间相差4(注:16进制9后面的数字为字符)
  • 数组随着下标的增长,地址是由小到大变化的

正好一个整形在内存中占4个字节,因此我们得出:

数组在内存中是连续存放的

注意数组的数组名也是地址,其地址也是数组首元素的地址

这里没有打印,大家可以自己打印试试


8.sizeof 和strlen计算数组大小

在循环遍历数组时,我们有时候需要知道数组的大小,于是我们就可以使用sizeof运算符来计算数组的大小,sizeof()是用于获取数据类型或变量在内存中所占的字节数

:一个整形在内存中占4个字节,一个字符型占1个字节

如图:

注:sizeof最好使用%zd来进行打印

我们分别计算了整个整形数组大小以及整形数组第一个元素的大小

因此我们可以通过除法来计算元素个数:

通过比较数组元素确实为10个

同样的字符数组:

strlen:

strlen()只能计算字符串的长度,它是通过字符串末尾独有的\0结束标志来计算的,因此它在数组里可以用来计算初始化为字符串的字符型数组

如:

注:sizeof最好使用%zd来进行打印

通过上图我们发现通过sizeof会多计算一个元素,也就是\0,而strlen则不会

注意:上面ch字符数组的实际元素个数确实为8个,但我们实际用的元素一般是7个,注意甄别


9.小结:

  以上为一维数组的基本内容,下面开始介绍二维数组


三、二维数组

概念:我们把前面的一维数组作为一个元素放在一个数组里,这时候这个数组就是一个二维数组,

二维数组作为数组元素的数组就是三维数组,二维数组及以上都称为多维数组


1.语法

创建二维数组的语法如下:

type  arr_name[常量值1][常量值2];

常量1和常量2分别代表行和列

以上面arr数组为例:

  • 3表示数组有3行
  • 4表示数组一行有4个元素
  • int指定数组元素类型
  • arr为数组名,可以根据实际情况设定,名字要有意义


2.二维数组的初始化

二维数组也是像一维数组一样使用大括号进行初始化

二维数组也有完全初始化和不完全初始化,以及按行初始化,下面以整形二维数组为例:

完全初始化:

即每4个元素为一行,依次赋给arr

不完全初始化:

我们发现只有第一行的四个元素被依次赋值

二维数组按行初始化

如:int arr[3][2] = { {1,2},{3,4},{5,6} }

即使用大括号进行分行,大括号里面为每行的元素,此方法也适用于不完全初始化

如:

这样可以达到为每行不完全初始化的效果

注意:使用按行初始化,里大括号中的元素不能为空,如图:

所以使用行初始化,大括号里必须要有元素

另外需要注意的是:

二维数组初始化时,行可以省略,但是列不能省略

我们发现,虽然我们省略了行,但是编译器根据列数或者大括号数自动换行最终确定了行数

因此我们需要注意:列数不能省略,因为编译器不能根据行数来确定列数


3.二维数组的下标引用

通过前面观察我们也发现,二维数组的下标也都是从0开始的,

所以,例如:arr[0][0] 就表示第一行第一个元素,arr[0][1] 就表示第一行第二个元素,

arr[1][2] 就表示第二行第三个元素

如图:

除了打印,我们也可以通过下标索引进行赋值、改变值等操作,和一维数组一样,这里不再演示


4.二维数组的输入和输出

二维数组的输入和输出同一维数组一样,也是使用循环输入,不过是双层for循环

外层循环表示行,里层循环表示列

如:


5.二维数组在内存中的存储

对于这个问题,我们也通过打印每个元素地址来进行观察

如图:

通过观察,我们不难发现,每个元素的地址都相差4个字节,这是因为一个整形在内存中占4个字节

因此,我们可以得出:二维数组的每个元素在内存中都是连续存放的,地址也是由低到高

另外,我特意打印了数组名的地址,同一维数组一样,数组名的地址即为数组首元素的地址,

另外,对数组名取地址不用 & 符号,因为数组名就是一个地址


6.小结:

以上就是对二维数组的基本介绍,下面我们来继续介绍变长数组


四、C99中的变长数组

在C99标准之前,C语言在创建数组的时候,数组大小的指定只能使用常量、常量表达式,或者如果我们初始化数据的话,可以省略数组大小。

如:int arr[3] = {1,2,3}

       int arr[2+3] = {1,2,3,4,5}

       int arr[ ] = {1,2,3}

这种语法限制就导致我们只能在编译时确定数组大小,而不能在运行时确定数组大小

于是C99中给⼀个变长数组(variable-lengtharray,简称VLA)的新特性,允许我们使用变量来指定数组大小

如:

int n = 0;

scanf("%d", &n);

int arr[n];

上面的arr数组就是变长数组,因为它数组大小就是由变量n来确定,编译器只能在运行时确定数组大小,而不能在编译时就确定数组大小

因为变长数组只能在运行时确定大小,所以变长数组不能进行初始化,但是需要注意的是,变长数组的大小一旦确定后不能再通过改变变量来改变数组的大小,这和普通创建的数组是一样的

遗憾的是vs不支持变长数组,所以我无法演示变长数组,大家可以使用dev等内置了gcc编译器的IDE进行测试

大家也可以看看我在牛客网上做的一道题使用了变长数组

题目:

代码:


总结

以上就是关于本文的全部内容,希望对大家有所帮助,有问题欢迎评论区讨论

另外关于变长数组,其实不是真正的可变数组,在C语言中,借助一些库函数我们可以实现动态数组,那才是真正意义上的可变数组,动态数组我在后面会写到,欢迎大家的关注,诶嘿

  • 22
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 将C语言中的二维数组转换为一维数组,可以使用指针来实现。具体来说,可以先定义一个指向二维数组的指针,然后将该指针强制转换为指向一维数组的指针。在转换后,可以通过下标访问一维数组中的元素,即可完成将二维数组变为一维数组的操作。 下面是一个示例代码: ``` int main() { int a[2][3] = {{1, 2, 3}, {4, 5, 6}}; int *p = (int *)a; // 将指向二维数组的指针强制转换为指向一维数组的指针 for (int i = 0; i < 6; i++) { printf("%d ", *(p + i)); // 使用指针访问一维数组中的元素 } return 0; } ``` 输出结果为:1 2 3 4 5 6。 ### 回答2: 要将一个二维数组变成一个一维数组,可以使用循环遍历的方法来实现。下面是一个示例代码: ```c #include <stdio.h> #define ROWS 3 #define COLS 4 void flatten_array(int arr[ROWS][COLS], int* result) { int index = 0; for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { result[index++] = arr[i][j]; } } } int main() { int arr[ROWS][COLS] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; int flattened[ROWS * COLS]; flatten_array(arr, flattened); // 打印一维数组 for (int i = 0; i < ROWS * COLS; i++) { printf("%d ", flattened[i]); } return 0; } ``` 在上述代码中,通过定义一个 `flatten_array` 函数将二维数组 `arr` 转换为一维数组 `result`。函数使用两个嵌套的循环遍历二维数组的所有元素,并按顺序存储在一维数组中。在 `main` 函数中,在声明一个大小为 `ROWS * COLS` 的一维数组 `flattened`,并将二维数组 `arr` 转换为一维数组后存储在 `flattened` 中。最后,通过循环打印一维数组的所有元素,即可看到转换后的结果。 ### 回答3: 在C语言中,我们可以通过以下步骤将一个二维数组转换为一维数组: 1. 确定二维数组的行数和列数,并声明一个一维数组,使其大小等于二维数组的元素总个数。 例如,假设我们有一个3行4列的二维数组arr,那么一维数组的大小应为3 * 4 = 12。 2. 使用两层循环遍历二维数组的每个元素,并将其按行或按列的顺序复制到一维数组中。 例如,可以使用嵌套的for循环,外层循环遍历行,内层循环遍历列,然后将二维数组中的每个元素复制到一维数组中。 下面是一个示例代码: ```c #include <stdio.h> #define ROWS 3 #define COLS 4 void convert2DTo1D(int arr[ROWS][COLS], int newArr[], int totalElements) { int index = 0; for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { newArr[index] = arr[i][j]; index++; } } } int main() { int arr[ROWS][COLS] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; int totalElements = ROWS * COLS; int newArr[totalElements]; convert2DTo1D(arr, newArr, totalElements); // 打印一维数组 printf("一维数组:"); for (int i = 0; i < totalElements; i++) { printf("%d ", newArr[i]); } return 0; } ``` 上述代码将一个3行4列的二维数组转换为一个包含12个元素的一维数组,并将其打印出来。你可以根据需要修改二维数组的大小及其内容。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值