欢迎光临
我们一直在努力

数组与函数

目录

1.数组的概念

2.一维数组

2.1一维数组创建与初始化

2.2使用一维数组

2.3一维数组的存储

3.二维数组

3.1二维数组的创建

3.2二维数组初始化

3.3二维数组的使用

3.4二维数组的存储

4.函数

4.1自定义函数

4.2return语句

4.3数组作为函数参数

4.4函数的嵌套使用

4.5函数声明

5.static与extern

5.1static修饰局部变量

5.2static修饰全局变量

5.3static修饰函数


1.数组的概念

数组是一组相同类型数据的集合,注意是数据而不是数字的集合

数组中可以存放1或多个数据,元素个数不可为0

数组中所有数据的类型是相同的

数组分为一维数组和多维数组,二维数组比较常见

2.一维数组

2.1一维数组创建与初始化

一维数组的创建方式如下,数据类型根据内部存放的数据来决定,数组名可以根据实际需要或者使用方便取,[ ]内部是数组的元素个数即数组的大小

#include<stdio.h>
int main()
{
int arr1[10];//存放整型,大小为10
char arr2[5];//存放字符类型,大小为5

return 0;
}

一维数组与变量一样需要进行初始化,不然使用时容易出现问题

下面是数组的几种常用初始化方法,借此讲一下数组的类型

数组的类型其实就是除了数组名以外的部分

例如arr_1的类型就是int [5],arr_6的类型就是int [ ]

#include<stdio.h>
int main()
{
int arr_1[5] = { 1,2,3,4,5 };//完全初始化,将每个元素都写出来
int arr_2[5] = { 1,2,3 };//不完全初始化,只写出一部分元素,其余默认为0
int arr_3[5] = { 0 };//将全部元素初始化为0
int arr_4[5] = { 1 };//第一个元素为1,其余为0
int arr_6[] = { 1,2 };//如果元素全部写出,[]内部的常量可以不写

return 0;
}

2.2使用一维数组

当我们想使用数组内的数据时,可以通过下标来访问,第一个元素下表0,后续以此类推

如图将数组第二个元素7赋值给r,这就是数组的引用

#include<stdio.h>
int main()
{
int arr_1[5] = { 5,7,3,4,1 };
//下标 0 1 2 3 4
int r = arr_1[1];//7
printf("%d\\n", r);
return 0;
}

而有时需要使用数组来存储数据,但是数据需要运行时输入,而数组数据的输入和输入一个变量没有多大区别,如图,我们依次输入五个元素然后将其输出

#define _CRT_SECURE_NO_WARNINGS 1//在vs2022中使用scanf函数需要这一段代码
#include<stdio.h>
int main()
{
int arr[5] = { 0 };
for (int i = 0; i < 5; i++) {
scanf("%d", &arr[i]);//取出第i+1个元素的地址然后将输入的值赋给它
}
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]);//输出数组
}

return 0;
}

  而对于一个没有写长度数组我们可以使用sizeof函数快速获取其长度 

#include<stdio.h>
int main()
{
int arr[] = { 1,542,5,2,54,4,8,12,134,3 };
int len = sizeof(arr) / sizeof(arr[0]);//数组大小除以一个元素大小
printf("%d", len);
return 0;
}

2.3一维数组的存储

在一维数组中,所有元素是连续存储的,我们可以通过依次输出每个元素的地址来观察

地址的存储采用16进制,将最后两位化为10进制可以明显看到每个元素之间差了4个字节,正好是int类型的大小

3.二维数组

3.1二维数组的创建

将一维数组作为该数组的每个元素,那么该数组称为二维数组,下面是定义

#include<stdio.h>
int main()
{
int arr[5][3];
//和一维数组的定义基本相同,int表示内部存储的数据是整型
//arr是数组名可以根据需要取
//5表示5行,3表示三列,即每个一维数组的长度为3共有5个一维数组
return 0;
}

3.2二维数组初始化

#include<stdio.h>
int main()
{
int arr1[5][3] = { 1,2 };//不完全初始化,只初始化了第一行前两个元素,其余默认为0
int arr2[5][3] = { 0 };//不完全初始化,全部元素默认为0
int arr3[2][3] = { 1,2,3,4,5,6 };//完全初始化
int arr4[3][3] = { {1,2,3},{4,5,6},{7,8,9} };//按照行初始化
int arr5[][5] = { 1,2,3,4,5,6,7 };
//二维数组初始化可以不定义行,但是一定要知道有几列
// 1 2 3 4 5
// 6 7 0 0 0
//知道列大小根据元素个数可以补充完整数组,但是不知道列大小无法补充
int arr6[][5] = { {1,2},{2,3} };
// 1 2 0 0 0
// 2 3 0 0 0
//按照行初始化时每个数组也可以是不完全初始化
return 0;
}

3.3二维数组的使用

在使用二维数组时同样要使用下标来访问元素,在理解上我们可以当成行列的坐标

#include<stdio.h>
int main()
{
int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
// 1 2 3 4
// 5 6 7 8
// 9 10 11 12
//例如要取出11这个元素,那就是三行三列arr[2][2]
printf("%d\\n", arr[2][2]);
return 0;
}

类比一维数组,二维数组的输入输入也是类似的,不过多解释

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int arr[3][4] = { 0 };
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
scanf("%d", &arr[i][j]);
}
}
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("%d", arr[i][j]);
}
}
return 0;
}

3.4二维数组的存储

实际上二维数组中的元素并没有真的分为几行几列,所有数组都存在同一行

所以和一维数组一样,二维数组中的元素也是连续存储的,每两个元素之间相差四个字节

4.函数

C语言中的函数时完成某项特定任务的一小段代码,也被称为子程序

一般分为两类,库函数与自定义函数,库函数是C语言自带的只要引入相应头文件即可使用

在该网站可以详细了解不再赘述(C library – C++ Reference (cplusplus.com))

4.1自定义函数

当库函数不能满足我们的需要时,就得创建一个自定义函数来实现目的

一个自定义函数的定义方式如下,需要有返回类型,函数名以及传入参数,如果用不到任何参数形式参数部分可以不写

一般的函数进行的是传值调用,即在调用函数时将实际参数传入,用函数内部临时创建的临时变量来接收,函数运行完成后临时参数内存被释放而且不改变实际参数

由运行结果可知a和b的值并没有被修改,如果希望值被修改,则需要用指针传址调用,可以在我的指针部分的文章学习

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

void test(int x,int y) {
x = 10;
y = 20;
printf("x=%d y=%d\\n", x, y);
}
int main()
{
int a = 1;
int b = 2;
test(a, b);
printf("a=%d b=%d\\n", a, b);

return 0;
}

4.2return语句

在自定义函数使用过程中,经常需要使用return来返回函数的结果

1.当返回类型为void,可以写return ;

2.当return执行之后,后续程序不再执行

3.return的值如果和返回类型不同。会转换为函数返回类型

4.分支语句如果写了return,则每个分支都要有return返回

5.不写返回类型默认是int

6.写了返回类型但是没有使用return,则返回值未知

4.3数组作为函数参数

定义一个数组,然后使得每个元素加10,前后输出数组元素发现,数组的元素真实的被修改了

这就是一个传址调用,当传入数组的时候,其实传入的是数组的地址,直接通过地址修改数组元素是可以的,所以在函数内部求用sizeof求数组长度是不可以的,因为函数内部其实使用的是指针进行操作,得不到正确的结果

注意以下几个数组传参的要点

1.函数形参与实参个数要匹配

2.一维数组传参时,大小可以省略不写

3.二维数组传参时不能省略列大小,但是可以省略行大小

4.数组传参进去后,任何对数组的操作都是对实参数组本身进行的,不会创建一个临时数组

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void dis(int arr[], int len) {
for (int i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\\n");
}
void test(int arr[],int len) {
for (int i = 0; i < len; i++) {
arr[i] += 10;
}
}
int main()
{
int arr[5] = { 1,2,3,4,5 };
int len = sizeof(arr) / sizeof(arr[0]);
dis(arr, len);
test(arr, len);
dis(arr, len);

return 0;
}

4.4函数的嵌套使用

在一个函数中调用一个函数是可以的,因为函数本质就是一段实现特定功能的子程序段,相当于是将代码省略成一个函数替代,所以可以嵌套使用,但是不可以嵌套定义函数,每个函数都是独立定义的

#include<stdio.h>
void dis(int arr[], int len) {
for (int i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\\n");
}
void test(int arr[],int len) {
for (int i = 0; i < len; i++) {
arr[i] += 10;
}
dis(arr, len);//在函数内部使用另一个函数
}
int main()
{
int arr[5] = { 1,2,3,4,5 };
int len = sizeof(arr) / sizeof(arr[0]);
dis(arr, len);
test(arr, len);

return 0;
}

下面再讲一个printf函数的嵌套使用

#include<stdio.h>
int main()
{
printf("%d", printf("%d", printf("%d",43)));
//1 2 3
//首先我们要知道printf函数的返回值是多少
//printf函数的返回值是打印的字符个数
//所以第三个printf先打印43,返回2
//第二个printf函数打印2,返回1
//第一个printf函数打印1
//结果是4321
printf("\\n");
printf("%d\\n", printf("%d\\n", printf("%d\\n", 43)));
//注意\\n等转义字符也要计算在内
//输出为 43
// 3
// 2
return 0;
}

4.5函数声明

函数在使用前一定要先声明再调用

注意是声明而不是定义

int add(int x, int y);

只要写这么一行就算声明了函数,定义可以在调用之后的区域写,是没问题的,因为编译器从上往下扫描时,如果没有扫描到函数声明就使用了该函数,就会报错

在实际写代码时,我们可能会拆分成几个页面来写,以保持可读性与简洁性

因为库函数是包含在头文件里的,所以我们可以新建一个头文件,将需要的函数在其中声明

需要使用的时候包含头文件即可

5.static与extern

static可以修饰变量,extern可以引入变量

要解释这两个操作,先讲解一下生命周期与作用域

作用域就是一个变量可以合法使用的范围,局部变量的作用域在其所在的代码块,出了代码块就不起作用了,全局变量的作用域是整个程序

生命周期就是当一个变量被创建出来时,开始了它的生命周期,当它离开了它的作用域之后它的生命周期结束了,所以局部变量从被创建之后生命周期开始,离开所在的代码块之后生命周期结束,全局变量的生命周期从创建开始,到整个程序结束

5.1static修饰局部变量

static修改了局部变量的生命周期,当离开局部的作用域后它并没有被销毁,生命周期还在继续,直到整个程序的结束

观察下列代码,每次调用test函数的时候i被创建出来为0,然后加1输出1,离开函数后i被销毁

所以每次都输出1

那如果将i用static修饰呢,每次i都在加1并输出,所以依次输出1~5

因为static修改了i的生命周期,创建出来之后,只要对i进行操作,都是原来的i

相当于static int i=0只用了一次,负责将i创建并初始化,后续只剩下每次的i++

5.2static修饰全局变量

全局变量具有外链接性,意思是在很多个源文件中,我如果在其中一个源文件中定义了一个全局变量,加以正确的声明,它是可以被所有文件使用的

这就设计到extern的作用了,可以从外部引入变量或者函数

如下所示,当在test1.c中创建了一个全局变量a,在test.c中用extern声明就可以调用

而当用static修饰全局变量a时

程序就出现了错误,所以static修饰全局变量改变了其外链接性,使得它只能被本文件调用

5.3static修饰函数

同样的static修饰函数也是一样,函数也具有外链接性,所以当static修饰函数时,它也只能被本文件使用

                                  

赞(0)
未经允许不得转载:171主机测评 » 数组与函数
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址