C语言教程(十)数组

1. 简介

数组是一种存储于连续内存空间且具有相同类型的数据集合,也是一种随机存取的数据结构。数组中可以存取整数型、字符型、指针型等多种类型。

数组可以通过下标随机获取数组中的任意元素,而无需遍历整个数组,因此数组的存取效率很高。

数组也是一种数据类型,通常使用数组变量名来操作数组,在C语言中,还可以使用指针来操作数组,使其更加方便和灵活。

2. 数组声明与初始化

数组也是一种数据类型,也需要先声明初始化后才能使用。具体形式为:类型说明符 变量名[元素个数];

int arr[5];//声明数组

上面的示例声明了一个数组arr,包含5个int类型的元素,数组名与变量名的命名规则一样,以小写为主,数据类型可以是C语言中的任意有效类型,且元素个数必须大于0。

数组的初始化分为两种,一种是使用大括号{}对每个元素进行逐个赋值,元素个数可以不写,自动确定数组长度,注意:这种初始化方式必须和声明在同一行,而不能声明和初始化分开:

int arr[5] = {1,2,3,4,5};//正确,对每个元素初始化
int arr[] = {1,2,3};//自动确定数组长度为3

int arr[5];
arr = {1,2,3,4,5};//报错

如果初始化的元素个数少于数组的元素,那么未赋值的元素将初始化为0:

int arr[5] = {1,2,3};//初始化了前3个元素
int arr[5] = {1,2,3,0,0}//这与上面的初始化是相同的

//将数组所有元素初始化为0
int arr[5] = {0};

还可以为指定位置的元素进行赋值,还可以和顺序赋值结合使用:

int arr[5] = {[0] = 1,[3] = 5};//为指定位置元素赋值
int arr[5] = {1,[3] = 3,10};//指定位置和顺序结合使用

上面的示例为指定位置元素赋值中,为第1个元素和第4个元素赋值;第二条语句结合顺序赋值分别对第1、4、5个元素进行了赋值。

第二种方式就是通过下标对数组的指定元素赋值,数组的下标是从0开始的,所以最后一个元素的下标就是整个数组的长度减1。如果对不存在的元素赋值,就会发生越界。

int arr[5];
arr[0] = 1;//通过下标赋值
arr[4] = 10;
arr[5] = 5;//越界,编译器不管

上面的示例中,分别对数组arr的第一个元素和最后一个元素进行了赋值,但是使用arr[5]即对数组的第6个元素进行了赋值,这个元素并不存在,所以就会发生越界访问错误。在C语言中,编译器并未对数据越界行为进行处理,也不会提示错误,而是对数组后面的内存地址进行了赋值,这是一种很危险的行为。

同样,也可以通过数组下标来访问数组元素:

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

int a = arr[3];//获取数组中第4个元素的值
//循环获取数组中的元素
for(int i = 0;i < 10;i++){
  printf("元素[%d] = %d\n",i,arr[i]);
}

3. 数组长度

数组可以通过sizeof运算符,返回以字节为大小的长度,除以数组元素的大小,就是数组元素的个数。

int arr[5] = {1,2,3};
int length = sizeof(arr);//20个字节
int num = sizeof(arr) / sizeof(arr[0]);//元素数量为5

printf("数组的长度为%zu\n",length);//20
printf("数组的元素个数为%zu\n",num);//5

上面的示例中数组arr有5个元素,且都是int类型的,所以每个元素都是4个字节,数组的长度就是20,sizeof(arr[0])是首个数组元素的字节长度,所以两者相除就能得到元素的个数;由于sizeof运算符的返回值类型为size_t,所以printf()函数的占位符使用%zu。

4. 数组的地址

C语言中,数组在内存中表示为一段连续的内存空间,所以只要获取到第一个元素的内存地址,后面的其他元素地址都能推算出来。数组通常与指针结合起来使用。

int arr[5] = {1,2,3};
int *p = NULL;
p = &arr[0];//获取第一个元素的地址

指针变量是存储内存地址的,所以声明了指针变量p来存储数组第一个元素arr[0]的地址,也就是整个数组的起始地址。

为了更方便的获取数组的地址,C语言中提供了更为方便的表示方式,直接使用数组名就可以获取数组的地址,数组名是一个常量指针,是不可更改的。它不是直接表示地址的,而是进行了内部转换。

int arr[5] = {1,2,3};
int *p = arr;//使用数组名获取数组地址,和&arr[0]的结果是一样的

5. 数组指针

数组指针就是指向数组的指针,指向的对象是数组,指针变量存放的是数组的首地址。

一般在实际的项目中,使用“指针获取地址”方式访问数组的元素比较普遍,通常使用数组名加上元素索引来遍历整个数组,它和通过下标方式访问数组的元素是等价的。

int arr[5] = {1,2,3,4,5};
for(int i = 0;i < 5;i++){
   printf("数组元素的地址为%d\n",*(arr + i));  //arr[i]等同于*(arr + i)
}

上面的示例中,*(arr + i)表示数组名、*取值符再加上索引遍历每个元素的值,等同于arr[i]。

当然,如果将数组的地址存到指针变量中,那么就可以使用指针变量来遍历数组元素了。

int arr[5] = {1,2,3,4,5};
int *p = arr;

for(int i = 0;i < 5;i++){
   printf("数组的元素为%d\n",*p);
   p++;//指向下一个数组元素的地址
}

数组作为函数的参数时,可以传入一个数组,也可以传入一个数组指针变量。

int arr[5] = {1,2,3,4,5};
//数组作为参数传入函数
int func(int arr[]);//传入数组
//等价于
int func(int *arr);//传入指针变量

6. 多维数组

C语言中,还可以声明存取多个维度的数据,也就是多维数组,本质上还是一维数组,在内存中还是按照一维数组的方式连续存储的,如果是按行来计算,即先存储第一行数组的元素,再存储第二行数组的元素,然后通过内存偏移(移动指针)来访问每一个数据元素。

int arr[2][3];//声明一个二维数组

int arr2[2][3] = {  //声明一个二维数组并初始化
   {1,2,3},//第一行
   {4,5,6} //第二行
}

上面示例中,声明了一个二维数组arr,第一个维度有2个元素,第二个维度有3个元素;声明并初始化了一个二维数组arr2,在内存中先存储第一行的数据即{1,2,3},再存储第二行的数据即{4,5,6}。

二维数组初始化的嵌套的大括号是可以省略的,直接顺序初始化元素,存储的原理也是连续存储:

int arr[2][3] = {1,2,3,4,5,6};
//等价于
int arr[2][3] = {  //声明一个二维数组并初始化
   {1,2,3},//第一行
   {4,5,6} //第二行
}

通过数组的下标(行下标和列下标)可以访问二维数组的元素,通过嵌套for循环的方式实现。

int arr[2][3] = {  //声明一个二维数组并初始化
   {1,2,3},//第一行
   {4,5,6} //第二行
}
for(int i = 0;i < 2;i++){ //嵌套for循环获取二维数组arr的每个元素
   for(int j = 0;j < 3;j++){
      printf("arr[%d][%d] = %d\n", i, j, arr[i][j]);
   }
}

7. 变长数组VLA

C99标准中引入了一种新型数组,允许程序员可以使用变量来控制数组的长度,即数组的长度不再是常量,而是由变量自由控制,由运行时确定,这就是变长数组,即VLA(variable-length array)。

变长数组只能在函数内作为局部变量使用,即不能使用extern或static变量说明符。

int length;
int arr[length];//定义数组长度

for(int i = 0; i < length; i++){  //循环初始化
   arr[i] = i;
}

8. 总结

  • 数组是一种存储于连续内存空间且具有相同类型的数据集合;
  • 数组的声明使用[]符号,初始化可以使用下标[]或者大括号{}来实现;
  • 数组的元素可以用下标[]或者指针来获取,arr[i]和*(arr + i)是等价的;
  • 数组的地址可以通过第一个元素的地址获取,也可以直接使用数组名获取;
  • 数组也可以定义多维数组,他们也是存储于连续的内存空间中;
  • C99标准引入了变长数组,即数组的长度由变量确定的。
觉得有帮助可以赞赏本文哦~万分感谢!
文章:C语言教程(十)数组
作者:沛旗
链接:https://www.peiqiblog.com/article/2265/
版权声明::本博客站点所有文章除特别声明外,均采用 CC BY-NC-SA 4.0协议
转载请注明文章地址及作者哦~
暂无评论

发送评论(禁止发表一切违反法律法规的敏感言论) 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇