数组的基本概念
- 数组,从字面上看,就是一组数据的意思,没错,数组就是用来存储一组数据的;
- 在C语言中,数组属于构造数据类型;
- 如果想要同时保存多个相同类型 的数据时候,就要想到数组;
定义数组:
- 格式: 元素类型 数组名[元素个数];
- 元素: 数组中保存的每一个数据就是元素;
- 元素类型: 数组中存储的数据类型;
- 数组名称: 变量的名称
- 元素个数: 告诉数组要存储多少个数据;
// int 元素类型
// ages 数组名称
// [10] 元素个数
// 定义一个可以存储10条数据,每条数据的数据类型都是int类型;
int ages[10];
// 存储空间总共存储40字节;
初始化数据
-
定义的同时初始化
-
指定元素个数,完全初始化
- 其中在{}中的各数据即为各元素的初值,各值之间用逗号隔开;
int ages[3] = {1, 2, 3};
-
不指定元素个数,完全初始化
- 注意点: 如果定义的同时初始化,并且没有指定元素的个数, 那么元素的个数就是初始化的个数
int nums[] = {1, 2, 3, 4, 5}; // int nums[5];
-
指定元素个数,部分初始化
- 注意点: 没有显示初始化的元素,那么系统会自动将其初始化为0;
int nums[10] = {1, 2};
-
指定元素个数,部分初始化
- 给指定元素赋值,其它元素系统会自动将其初始化为0
int nums = {[4] = 3, [1] = 2};
-
先定义再初始化(完全初始化)
- 注意点:
- 1.如果定义的同时不初始化,那么元素的个数不能省略;
int age1[]; // 报错
- 如果先定义再初始化,那么就不能够一次性初始化,会报错
int ages[3]; ages = {4, 6, 9}; // 报错
- 正确初始化
int nums[3]; nums[0] = 1; nums[1] = 2; nums[2] = 3;
- 注意点:
-
先定义再初始化(部分初始化)
- 注意点: 如果只进行了部分初始化, 那么没有被初始化的元素不会赋值为0
int nums[4]; nums[1] = 2; nums[3] = 6; printf("nums[0] = %i\n", nums[0]); // 4200288 非0 printf("nums[2] = %i\n", nums[2]); // 85 非0
数组的遍历
- 什么是数组的遍历
- 遍历数组就是取出数组中存储的所有数据,我们就称为遍历数组;
// 简单遍历数组
int ages[] = {1, 3, 5};
printf("ages[0] = %i\n", ages[0]);
printf("ages[1] = %i\n", ages[1]);
printf("ages[2] = %i\n", ages[2]);
- 循环遍历数组(推荐)
- 注意点: 在遍历数组的时候,循环结束的条件不要写的太死
int ages[] = {1, 3, 5};
for(int i = 0; i < 3; i++){
printf("ages[%i] = %i\n", i, age[i]);
}
数组长度的计算方法
-
因为数组在内存中占用的字节数取决于其存储的数据类型和数据的个数
- 数组所占用存储空间 = 一个元素所占用存储空间 * 元素个数(数组长度);
-
计算数组可以使用以下方法
- 数组的长度 = 数组占用的总字节数 / 数组元素占用的字节数
-
方法1:
int length = sizeof(ages) / sizeof(int);
- 方法2:
int length = sizeof(age) / sizeof(age[0]);
#include <stdio.h>
int main()
{
int nums[5] = {1, 3, 5, 7, 9};
int len = sizeof(nums) / sizeof(nums[0]);
// 正序遍历数组
for(int i = 0; i < len; i++){
printf("nums[%i] = %i\n", i, nums[i]);
}
printf("-------------------------------\n");
// 逆序遍历数组
for(int j = len -1 ; j >= 0; j--){
printf("nums[%i] = %i\n", j, nums[j]);
}
return 0;
}
数组在内存中的存储细节
-
定义数组分配内存的规则
- 给整个数组分配内存的时候,和普通变量一样,是从内存地址大的开始分配
- 给数组中的每一个元素分配内存空间的时候,是从已经分配好的内存地址最小的开始分配;
-
往数组中存储数据的规则
- 和变量往内存中存储数据一样,从自己占用内存地址比较大的开始存储
int num1[3];
num1[0] = 1; //0000 0000 0000 0000 0000 0000 0000 0001
num1[1] = 3; //0000 0000 0000 0000 0000 0000 0000 0011
num1[2] = 5; //0000 0000 0000 0000 0000 0000 0000 0101
printf("&num = %p\n", &num1); // &num = 0028FEB4
printf("&num[0] = %p\n", &num1[0]); // &num[0] = 0028FEB4
printf("&num[1] = %p\n", &num1[1]); // &num[1] = 0028FEB8
printf("&num[2] = %p\n", &num1[2]); // &num[2] = 0028FEBC
![](https://img.haomeiwen.com/i7924287/e95b941552d39bec.jpg)
使用数组时候的注意点(越界问题)
- 数组的索引是从0开始的
- 如果索引不在数组的规定的索引范围内,那么有可能会报错,也有可能取出一个不是自己的值
- 注意点:在使用数组的过程中,一定不要超过数组索引的范围;
char ch1[2] = {'a', 'b'};
char ch2[2] = {'c', 'd'};
printf("ch1[-1] = %c\n", ch1[-1]); // d
printf("ch2[2] = %c\n", ch2[2]); // a
printf("ch2[22] = %c\n", ch2[22]); // ' ';
![](https://img.haomeiwen.com/i7924287/275ce1572181248a.jpg)
- 在定义数组的时候,数组的元素个数只能放常量或者常量表达式
// 元素个数是一个常量
int nums1[4];
// 元素个数是一个常量表达式
int nums2[2+2];
// 变量
int a = 6;
int nums3[a]; // 在企业开发开发中不要这样使用
int nums4[a] = {1, 3, 5}; // 会报错
数组和函数
- 数组可以作为函数的参数使用,数组用函数参数有两种形式
- 一种是把数组元素作为实参使用
- 一种是把数组名作为函数的形参和实参使用;
数组元素作为函数参数
-
首先了解一下基本类型作为函数的参数
- 基本类型作为函数的参数, 在函数中修改形参的值不会影响到外界实参的值;
#include <stdio.h> void change(int a); int main() { int num = 66; printf("num = %i\n", num); // 66 change(num); printf("num = %i\n", num); // 66 return 0; } void change(int a){ a = 111; }
-
数组元素作为参数, 那么在函数中修改形参的值,会影响到外面实参的值
- 数组名作函数参数时,实参与形参之间不是"值传递",而是"地址传递";
#include <stdio.h>
void change2(int nums[]);
int main()
{
int nums[4] = {1, 3, 5, 7};
printf("nums[1] = %i\n", nums[1]); // 3
change2(nums);
printf("nums[1] = %i\n", nums[1]); // 666
return 0;
}
// 实参与形参之间不是"值传递",而是"地址传递";
// 既然都是保存 同一个地址,所以都可以操作这块内存
void change2(int nums[]){
nums[1] = 666;
}
定义一个数组,用于遍历数组
#include <stdio.h>
void printArray(int nums[]);
int main()
{
//定义一个数组,用于遍历数组
int nums[4] = {1, 3, 5, 7};
printArray(nums);
return 0;
}
// 因为外面传入是一个地址,所以这里接收到的也是一个地址
// 在C语言中所有地址都是用指针类型接收的
// 指针类型在32位编译器中占用4个字节,在64位编译器中占8个字节
// 结论: 当数组作为函数参数时,没办法在函数内存动态计算数组的长度;
void printArray(int nums[]){
int len = sizeof(nums) / sizeof(nums[0]);
printf("len = %i\n" , len); // 1
}`
-
结论: 当数组作为函数参数的时候,没有办法在函数内存动态计算数组的长度
-
正确写法:
#include <stdio.h>
void printArray(int nums[], int len);
int main()
{
//定义一个数组,用于遍历数组
int nums[4] = {1, 3, 5, 7};
// 先在main中计算出数组的长度,然后传入
int len = sizeof(nums) / sizeof(nums[0]);
printArray(nums, len);
return 0;
}
void printArray(int nums[], int len){
for(int i = 0; i < len; i++){
printf("nums[%i] = %i\n", i, nums[i]);
}
}
- 设计一个函数找出数组元素的最大值;
#include <stdio.h>
int getMax(int nums[], int len);
int getMax2(int nums[], int len);
int main()
{
// 设计一个函数找出数组元素的最大值
int nums[5] = {3, 34, 6, 9, 17};
// 计算数组的长度
int len = sizeof(nums) / sizeof(nums[0]);
int max = getMax(nums,len);
printf("Max = %i\n", max);
int max2 = getMax2(nums,len);
printf("Max2 = %i\n", max2);
return 0;
}
// 第一种: 把max当做是数组的第一个元素
int getMax(int nums[], int len){
int max = nums[0];
for(int i = 1; i < len; i++){
if(max < nums[i]){
max = nums[i];
}
}
return max;
}
// 第二种: 把max2当做是索引号
int getMax2(int nums[], int len){
int max2 = 0;
for(int i = 1; i < len; i++){
if(nums[max2] < nums[i]){
max2 = i;
}
}
return nums[max2];
}
- 从键盘输入3个0~9之间的数, 然后输出0~9中哪些数字没有出现过
#include <stdio.h>
int main()
{
// 从键盘输入3个0~9之间的数, 然后输出0~9中哪些数字没有出现过
// 定义数组保存用户输入的数据
// 注意点: 为什么要定义一个可以存储10个元素的数组
// 因为可以存储10个元素的数组,索引正好是0~9
int nums[10] = {0};
int len = sizeof(nums) / sizeof(nums[0]);
// 定义变量保存用户输入的数据
int value = -1;
for(int i = 0; i < 3; i++){
printf("请输入一个0~9数,以回车键结束\n");
scanf("%i", &value);
nums[value] = 666;
};
printf("---------------------\n");
for(int i = 0; i < len ; i++){
if(nums[i] != 666){
printf("i = %i\n", i);
}
}
return 0;
}
网友评论