C语言学习第七天

英文:
void:没有,空
extern:外部的,在外面可以使用
function:函数,功能
implicit declaration of function ‘print:print函数没有声明
exit:出口,退出,结束
overflow:溢出,越界,装不下了
swap:交换
change:改变
g:global:全局
全局变量名要求以g_开头
static:静态
dynamic:动态

回顾:
1.goto语句
goto语句编程框架
2.空语句
有作用:耗费CPU死循环,延时(不准确)
有问题:for/while
3.一维数组(定长数组)
分配内存:定义变量
缺点:如果分配大量内存,代码繁琐,数组解决此问题
应用场景:分配大块内存,一次性分配
数组定义语法:元素数据类型 数组名[长度/数组元素个数] = {初始化表};
例如:int arr[3] = {1,2,3};
数组特点:分配的内存是连续的,数据类型是一致的,提前一次性分配好
数组定义的8种形式
元素访问:数组名[下标]
求数组占用的内存大小=sizeof(数组名)
求数组元素占用的内存大小=sizeof(数组名[0])
求数组元素个数/数组长度=sizeof(数组名)/sizeof(数组名[0])
for(i = 0; i < 一维数组长度; i++) {
修改元素或者查看元素
}
4.变长数组(了解)
5.二维数组
本质还是一维数组
元素是一维数组
定义二维数组的语法:元素数据类型 数组名[二维数组长度][一维数组的长度] = {初始化表}
数组定义的七种形式
一维数组元素:数组名[二维数组下标]
一维数组元素的元素:数组名[二维数组下标][一维数组下标]
求二维数组占用的内存大小:sizeof(数组名)
求二维数组中一维数组元素占用的内存大小:sizeof(数组名[0])
求具体某个元素占用的内存大小:sizeof(数组名[0][0])
求二维数组长度=sizeof(数组名)/sizeof(数组名[0])
求一维数组长度=sizeof(数组名[0]/sizeof(数组名[0][0]))
for(i = 0; i < 二维数组的长度; i++) {
for(j = 0; j < 一维数组长度; j++)
修改元素或者查看元素
}

6.函数(核心中的核心)
6.1.明确:任何C程序,C源文件都包含两部分内容:一对的变量(包括数组)和一堆的函数
6.2.函数概念:函数就是一堆语句的组合,用以实现一些相对独立并且具有一定通用性的功能
问:为何需要函数这个技术?
答:举例子
用户要求:实现两个正数相加
vim main1.c
int main(void)
{
int a;
int b;
int sum = 0;
scanf("%d%d", &a, &b);
if(a < 0 || b < 0) {
printf(“请重新输入正数.\n”);
return -1; //让程序结束,不能继续运行
}
//只有输入的数是正数才能加
sum = a + b;
printf(“sum = %d\n”, sum);
return 0;
}

  vim main2.c
  int main(void)
  {
int a;
int b;
int sum = 0;
scanf("%d%d", &a, &b);
if(a < 0 || b < 0) {
	printf("请重新输入正数.\n");
	return -1; //让程序结束,不能继续运行
}
//只有输入的数是正数才能加
sum = a + b;
printf("sum = %d\n", sum);
return 0;
  }

 vim add2.c ....add250.c :以上代码写250遍(有病!)
 分析结论:明显以上代码极其的繁琐啰嗦,代码重复重复的编写,加大开发的工作量
 期望:只需将以上重复的代码写一遍即可,其他文件只需使用即可,减少开发的工作量
 问:如何实现呢?
 答:目前采用函数这个技术
 终极解决方案:
 vim add.c
 //编写一个加法函数add
 int add(int x, int y)
 {
if(x < 0 || y < 0) {
	printf("请重新输入正数.\n");
	return -1; //让程序结束,不能继续运行
}
//只有输入的数是正数才能加
sum = a + b;
printf("sum = %d\n", sum);
return sum;
 }

vim main1.c
 int main(void)
  {
int a;
int b;
int sum = 0;
scanf("%d%d", &a, &b);
sum = add(a, b);
return 0;
  }

 vim main2.c
 int main(void)
  {
int a;
int b;
int sum = 0;
scanf("%d%d", &a, &b);
sum = add(a, b);
return 0;
  }

 vim main3.c ....main250.c 只需很轻松的用add函数即可

6.3.函数特点:
1.由一条或者多条语句组成
2.可以重复使用

6.4.函数使用三步骤(剑客):
a)函数声明:
1.函数声明的功能:告诉gcc编译器,将来这个函数可以给别人或者自己使用
函数声明是不分配内存空间的
2.函数声明的语法:extern 返回值数据类型 函数名(形参表);
建议:函数声明加extern(提高代码的可读性),理论上可以不加
3.函数声明特点:
1.如果函数定义在函数调用之前,可以省略函数声明,否则必须声明
2.该声明的没有声明,那么编译器gcc就会给个默认的函数什么,形式:
extern int 函数名(); //以后别这么干
3.函数名的命名遵循标识符的命名规则

b)函数定义:
1.函数定义功能:就是一个函数的具体实现过程,里面会包含一堆的语句
将来可以给别人或者自己使用
函数定义会分配内存
2.函数定义的语法:
返回值数据类型 函数名(形参表)
{
一堆的函数体语句;
} //花括号的作用就是圈语句用
例如:
int add(int x, int y) //x=100,y=200
{
return x + y;
}
x = 250; //报错
y = 251; //报错

 int main(void)
 {
sum = add(100, 200) = 300; //main函数使用add函数
return 0;
 }

3.函数定义特点:
1.返回值数据类型:就是函数运行完毕要给使用这个函数的代码返回一个数字
那么这个数组必然有对应的数据类型
如果函数没有返回值,返回值数据类型用void关键字
2.形参表:就是一堆的变量定义,这些变量只能在这个函数体内部使用,出了函数就不能用
形参的值由使用这些函数的代码来赋值,形参的变量有多个,用逗号,分开
如果使用函数的代码不想给函数传递参数,函数定义的时候形参表写void
建议:形参表变量定义的个数不要超过4个,要小于等于4个,否则影响函数
使用效率
例如:
int add(int x, int y, int z, int m) {} //漂亮
int add(int x, int y, int z, int m, int n) {} //代码的执行效率降低
3.函数的返回值:
如果函数需要返回一个数字,用关键字return,例如:return 返回值
切记:如果忘记了写return 返回值,gcc将来会返回一个随机数(非常可怕)
注意:返回值的数字的类型和函数定义时的返回值数据类型要一致
如果不一致,会进行隐式转换,可能造成数据的丢失
例如:int add(int x, int y)
{
int sum = x + y;
return sum;
}
如果函数没有返回值,可以不用写return或者写return后面不加内容!
例如:void add(int x, int y)
{
printf("%d\n", x+y);
return; //或者不写
}

c)函数调用:
1.函数调用功能:俗称使用函数,调用函数,访问函数
2.函数迪用语法:接收函数返回值的变量 = 函数名(实参表);
3.函数调用特点:
实参表:就是给函数的形参表赋的值
例如: sum = add(100, 200);//100,200就是实参,将来给add函数的x,y
实参的内存空间和形参的内存空间是独立的,地址是不一样的,但是里面存储的
数据是一样的!

d)函数使用的形式:
形式1:无参无返回值
例如: void 函数名(void)
{
函数语句;
}
形式2:无参有返回值
例如:int 函数名(void)
{
函数语句;
}
形式3:有参(1个形参)无返回值
例如:void 函数名(int x)
{
函数语句;
}
形式4:有参(多个形参,建议小于等于4个)无返回值
例如:void 函数名(int x, int y, int m, int n)
{
函数语句;
}
形式5:有参有返回值
例如:int 函数名(int x, int y, int m, int n)
{
函数语句;
}
形式6:参数不定有返回值(不建议这么做)
例如:int 函数名()
{
函数语句;
}

e)return关键字和exit函数
return关键字:实现函数返回
exit函数:让程序强制结束,为了使用此函数需要添加头文件:#include <stdlib.h>

f)实参和形参的那点事儿
形参就是实参的一份拷贝,实参给形参传递参数时,就是将实参里面的数字拷贝一份给形参

6.5.函数和数组的那点事儿
a)之前的代码都是研究函数如何操作变量,也就是函数如何操作通过变量分配的内存
问:函数如果要操作数组分配的内存,如何实现呢?
答:利用以下公式即可让函数和数组结合起来
b)函数访问数组编程公式
/定义访问数组的函数/
void 函数名(数组的首地址, 数组的长度)
{
可以查看数组元素
可以修改数组元素
}
例如:
void array_function(int a[], int lenght)
{
//查看数组元素的值
printf("%d\n", a[下标]);
//修改数组元素的值
a[下标] = 新值;
}
注意:
形参:int a[]本质就是一个数组的首地址,而不是数组,因为这么定义数组语法是不通过
函数通过这个地址访问元素时,可以当成数组来用
注意:等后期讲完指针时方可明白!

案例:定义两个元素的数组,利用函数将这两个元素互换
案例:利用函数将数组中某个元素的第n位清0
案例:利用函数将数组中某个元素的第n位置1
明确:不能用变量,因为如果是变量,形参是实参的拷贝,只能改变形参改变不了实参
要想改变,目前只能用函数和数组技巧

7.作用域和可见性
7.1.明确:C语言变量按照数据类型(占内存大小)分:12种(char…double)
7.2.明确:C语言变量按照作用域和可见性分两类:局部变量和全局变量
7.3.局部变量定义:定义在函数内部的变量
例如:
void A (void)
{
int a = 250; //局部变量
}
7.4.全局变量定义:定义在函数之外的变量
例如:
int g_b = 520; //全局变量
void A (void)
{
int a = 250; //局部变量
}
int g_c = 521; //全局变量

7.5.static关键字
如果定义变量时前面加static关键字修饰,表示此变量为静态变量
如果定义变量是前面么有加static关键字修改,表示此变量为非静态变量
例如:
int a = 250; //非静态变量
static int a = 250; //静态变量

7.6.终极结论:最终C语言变量按照作用域和可见性来分,最终分四大类:
局部非静态变量/局部静态变量/全局非静态变量/全局静态变量

7.7.详解局部非静态变量特点:
a)形式1:
void A(void)
{
printf(“a = %d\n”, a); //不可以,报错,gcc编译时报没有定义的错误
int a = 250; //定义局部非静态变量
printf(“a = %d\n”, a); //可以
}

b)形式2:
void A(void)
{
if(1) {
int a = 250;
printf(“a = %d\n”, a); //可以
}
printf(“a = %d\n”, a); //不可以,报错,gcc编译时报没有定义的错误
}

c)函数的形参
void A(int a) //a在整个函数体内都可以用,出了函数不能用

d)局部非静态变量特点
1.此变量使用范围:从定义的地方开始依次向下直到最近的花括号结束
注意:if…else/switch…case/for/while/do-while
2.此变量分配的内存生命周期:从定义的地方操作系统就会给变量分配内存
直到最近的花括号操作系统立马收回变量的内存
只能等下一次运行这些代码才能给变量重新分配内存

7.7.详解局部静态变量特点(钉子户):
a)形式1:
void A(void)
{
printf(“a = %d\n”,a);//不可以,报错,gcc编译时报没有定义的错误
static int a = 250; //局部静态变量
printf(“a = %d\n”,a); //可以
}
b)形式2:
void A(void)
{
if(1) {
static int a = 250; //局部静态变量
printf(“a = %d\n”,a); //可以
}
printf(“a = %d\n”,a);//不可以,报错,gcc编译时报没有定义的错误
}

c)局部静态变量特点:
1.此变量使用范围:从定义的地方开始到最近的花括号结束
2.此变量分配的内存生命周期:从定义的地方开始分配内存直到程序结束
一次分配,程序不结束,下次不会分配,接着上一次的使用
程序不结束,下次就不会重新分配内存
3.由衷建议:少用此类变量

7.8.详解全局非静态变量:
a)形式1
void B(void)
{
printf(“g_a = %d\n”, g_a); //不可以,gcc报没有定义的错误
}

int  g_a = 10; //定义初始化全局非静态变量

void A(void)
{
printf(“g_a = %d\n”, g_a); //可以,函数内部访问全局非静态变量
}
void C(void)
{
printf(“g_a = %d\n”, g_a); //可以,函数内部访问全局非静态变量
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值