C语言基础-函数

为什么会有函数

  • 封装一些常用的功能,在使用时只需要调用函数即可,不需要了解其中的具体复杂代码实现,使主程序的结构更清晰
    • 比如我们经常使用printf()来进行在控制台打印,不需要知道printf的具体实现,只需要调用即可,并且在主程序中看到printf就知道是要打印信息用,程序清晰明了
  • 模块化一些经常需要复用的代码,复用时不需要复制整个代码,只需要调用函数即可,使程序编写更加高效、易用
  • 便于将程序组织到多个文件中程序结构更加合理自然
    • 比如我们在调用printf时,需要先导入库函数中的头文件stdio.h,只有导入了这个头文件,我们才能使用printf函数,c语言已经帮我们做好了很多函数功能,放在不同的文件中。
函数基础
函数语法

函数需要先声明后使用。

  • 函数声明在前,中间可调用,定义实现在后
  • 函数不声明,直接定义实现在前,随后有调用

声明格式

函数返回值类型 函数名(函数接收的参数类型 参数名,....可以有多个参数);
  • 其中函数返回类型可以省略,省略的话默认返回是int类型
  • 函数接受参数列表也是可以省略的,省略的话表示该函数直接调用即可,不需要向函数中传递参数
  • 注意,不能在一个函数中定义另一个函数,main也是一个函数,是C程序执行的入口函数

函数定义实现

函数返回值类型 函数名(函数接收的参数类型 参数名,....可以有多个参数){
	函数具体的实现代码
	.....
	return 表达式; //如果函数需要有返回值的话,需要通过return返回值,该值会被转换成返回值类型
}
  • 就是将声明结尾的;替换为{代码实现}

代码示例

#include <stdio.h>

int sum(int max); //声明一个sum函数,计算0+1+2+...+max的值并返回

int main(int argc, char const *argv[])
{
	//调用函数
	printf("sum = %d\n", sum(10));
	//再次调用
	int a = sum(200); //函数返回值可以赋值给变量之后使用
	printf("a = %d\n", a);
	
	return 0;
}

// 函数定义功能实现
int sum(int max){
	int sumValue = 0;
	for(int i = 0; i <= max; i++){
		sumValue += i;
	}
	
	return sumValue;
}

运行结果:

sum = 55
a = 20100
内部变量

定义在函数内部或者函数参数列表部分的变量

  • 注意,由于main也是函数,所以在main中定义的变量也是内部变量
    可使用范围(作用域)
  • 只能在声明变量的函数内部使用
  • 多个不同的函数中可以声明相同名字的内部变量,互不影响
    生命周期
  • 从函数开始被调用开始,到函数退出,变量消失

代码示例

#include <stdio.h>

int sum(int max); //声明一个sum函数,计算0+1+2+...+max的值并返回

int main(int argc, char const *argv[])
{
	int a = 10; //内部变量
	printf("main-a is %d\n", a);
	
	sum(10); // main中的a和sum中的a互不干扰
	printf("main-a is %d\n", a);
	sum(20); // 上一次函数退出后a和b重新初始化
	
	return 0;
}

int sum(int max){
	int a = 0; //不同函数中可以声明同名内部变量
	int b = 100;
	for(int i = 0; i <= max; i++){
		a += i;
	}
	printf("sum-a is %d\n", a);
	printf("sum-b is %d\n", b);
	
	return a;
}

运行结果:

main-a is 10
sum-a is 55
sum-b is 100
main-a is 10
sum-a is 210
sum-b is 100
外部变量

定义在函数外部的变量。
可使用范围(作用域)

  • 声明的位置到文件末尾的全局都可以使用,可以在多个函数中和外部使用
  • 一个程序的多个源文件中不能定义同名外部变量,可以使用extern关键字声明使用其他文件中定义的外部变量
  • 当内部变量与外部变量同名时,内部变量优先级高,这种情况要避免出现
    生命周期
  • 程序运行整个周期中都存在,不会因为某一个使用外部变量的函数退出而消失

代码示例

#include <stdio.h>

int sum(int max); //声明一个sum函数,计算0+1+2+...+max的值并返回

int a = 20; //外部变量a,之后的函数中都可以使用

int main(int argc, char const *argv[])
{
	int a = 10;
	printf("main-a is %d\n", a);//内部变量a的优先级更高
	
	sum(10);
	sum(1); //验证外部变量不会因为某一函数退出而消失
	
	return 0;
}

int sum(int max){
	for(int i = 0; i <= max; i++){
		a += i;//修改外部变量
	}
	printf("sum-a is %d\n", a);
	
	return a;
}

运行结果:

main-a is 10
sum-a is 75
sum-a is 76
关键字extern

作在外部变量还没有定义时使用该变量,或者外部变量的定义和使用不在同一个源文件中时,在变量声明时,必须加上extern关键字。
变量声明

  • 说明变量的类型,不会实际为变量分配存储空间
extern int a;//这种就只是在使用外部变量时先声明,但是不会给变量分配存储空间

变量定义

  • 声明变量类型,并为变量实际分配存储空间
int a;//在外部变量真正定义的地方,才会对外部变量进行存储空间的分配

代码示例

#include <stdio.h>

int main(int argc, char const *argv[])
{
	extern int a; //声明使用之后定义的外部变量,如果不写这句将不在外部变量a的作用域内
	
	printf("a is %d\n", a);
	
	return 0;
}

int a = 100; //外部变量定义

运行结果:

a is 100
静态变量

static修饰的变量或函数。

  1. 修饰外部变量
    • 该外部变量只能在被定义的源文件中被使用,不能被其他文件访问
    • 这样其他文件中就可以声明同名外部变量
      代码示例
      源文件1:exercise2-2.h
int function1(int a, int b);

源文件2:exercise2-2.c

#include "exercise2-2.h"

static int s = 100;

int function1(int a, int b){
	return s; //静态外部变量只能在当前源文件中使用
}

源文件3:exercise2-1.c

#include <stdio.h>
#include "exercise2-2.h"

int main(int argc, char const *argv[])
{
	// extern int s;
	// printf("s = %d\n", s);// 直接访问static外部变量是不行的
	printf("function result is %d\n", function1(1, 2));
	return 0;
}

运行结果:

function result is 100
  1. 修饰函数
    • 该函数只能在被定义的源文件中被使用,不能被其他文件访问
    • 其他文件中也可以声明同名函数
      代码示例
      源文件1:exercise2-2.h
static int function1(int a, int b);
int function2(int a, int b);

源文件2:exercise2-2.c

#include "exercise2-2.h"

static int function1(int a, int b){ //静态函数,只能当前源文件中使用
	return (a + b) / 2;
}

int function2(int a, int b){
	return function1(a, b); //同一文件中可以使用function1
}

源文件3:exercise2-1.c

#include <stdio.h>
#include "exercise2-2.h"

int main(int argc, char const *argv[])
{
	// function1(1,2); //由于function1只能在源文件2中使用,该语句会引起编译器报错
	int s = function2(1, 2); // function2可以正常调用
	printf("s = %d\n", s);
	
	return 0;
}

运行结果:

s = 1
  1. 修饰内部变量
    • 变量在函数生命周期结束后依然存在,再次进入函数时变量保持上次退出时的值,不新做初始化
    • 不过它的作用域依然只限定在函数内使用

代码示例

#include <stdio.h>

int sum(int max);

int main(int argc, char const *argv[])
{
	sum(10);
	sum(1);
	
	return 0;
}

int sum(int max){
	static int a = 1; //静态内部变量,不会随着函数的结束而消失
	for(int i = 0; i <= max; i++){
		a += i;
	}
	
	printf("sum-a is %d\n", a);
	return a;
}

运行结果:

sum-a is 56
sum-a is 57
各种类型变量的初始化情况
  1. 在不进行显示初始化时
    • 外部变量和静态变量默认值为0
    • 内部变量值为不确定值
  2. 初始化
    • 外部变量和静态变量初始化时必须使用常量表达式,且只能初始化一次
    • 内部变量则随函数的调用反复进行初始化,初始化表达式中可以用之前已经定义过的任意值和常量

代码示例

#include <stdio.h>

int ex_a; //外部变量不显示初始化,默认为0
int ex_b = 100;

int main(int argc, char const *argv[])
{
	int a;//内部变量不显示初始化,值不确定
	int b = 10;
	
	printf("ex_a = %d\n", ex_a);
	printf("ex_b = %d\n", ex_b);
	printf("a = %d\n", a);
	printf("b = %d\n", b);
	
	return 0;
}

运行结果:

ex_a = 0
ex_b = 100
a = 1 //这个值大家运行结果可能会不同
b = 10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值