函数 域
- C语言--备忘
- 一、函数定义
- 二、函数声明
- 三、函数定义
- 四、函数调用
- 五、函数使用
- 形式1:无参数无返回值
- 形式2:无参数有返回值
- 形式3:有参数无返回值
- 形式4:有参数无返回值
- 形式5:有参数有返回值
- 形式6:return关键字和exit函数
- 要点说明:
- 六、函数和数组
- 七、作用域与可见性
- 局部与全局
- 形式一:局部非静态变量
- 形式二:局部 静态变量 (钉子户)
- 形式三:全局 非静态变量
- 1. 在同一源文件
- 2. 在不同源文件
- 形式四:全局 静态变量
- 总结
一、函数定义
- 函数就是一堆语句的组合,可以实现一些相对独立和通用性的功能;
- 任何C语言,包括一对变量(包括数组)和一堆的函数
- 解决繁琐代码,重复编写,加大开发量;为解决这个问题,使用函数这个技术,只需编写一遍;
- 将公共代码独立化;
return -1; //一般用来让程序结束,不能继续运行
return 0; //表示程序运行成功
- 函数声明三步骤
1.1 函数声明:告诉gcc,将来这个函数可以给别人或者自己用,函数声明不分配内存空间
1.2 函数声明的语法:
1.3 如果函数定义在函数调用之前,可以省略函数声明,否则必须声明 ;
extern 返回值数据类型 函数名(形参表)
建议:函数声明加extern ,提高代码可读性;
三、函数定义
函数定义:
- 函数定义功能:就是一个函数的具体实现过程,里面包含语句,可被其他调用;
- 函数定义语法:
返回值数据类型 函数名(形参表)
{
一堆的函数体语句;
}
int add(int x, int y)
{
return x+y;
}
int main(void)
{
int sum= add(100,200);
return 0;
}
四、函数调用
- 函数调用功能:俗称使用函数,调用函数,访问函数
- 调用语法:接收函数返回值的变量 = 函数名(实参表)
- 函数调用特点:实参表- 就是给函数形参表赋值的值
sum=add(100,200);//100、200就是实参
// 实参的内存空间和形参的内存空间实独立的,地址不相同,但存储的数据相同
五、函数使用
形式1:无参数无返回值
void 函数名(void)
{
函数语句;
}
形式2:无参数有返回值
int 函数名(void)
{
函数语句;
}
形式3:有参数无返回值
void 函数名(int x)
{
函数语句;
}
形式4:有参数无返回值
建议小于4个,影响运行效率
void 函数名(int x,int y,int m,int n)
{
函数语句;
}
形式5:有参数有返回值
建议小于4个,影响运行效率
int 函数名(int x,int y,int m,int n)
{
函数语句;
}
形式6:return关键字和exit函数
- return:实现函数返回
- exit: 让程序强制结束,为使用次函数需添加 #include
#include
#include
void print(void)
{
printf("1.\n");
exit(0);//程序到此结束
//return;//程序返回至main函数,继续执行
printf("2.\n");
}
int main(void)
{
print();
printf("3.\n");
return 0;//让程序正常结束,0表示正常
}
要点说明:
#include
extern void print(int a,int b,int c, int d);
extern int read(void);
// 自定义 print 函数
void print(int a,int b, int c, int d)
{
printf("a、b、c、d的四个变量的地址为%p,%p,%p,%p",&a,&b,&c,&d);
//abcd的值与main函数相同,但是地址不同
return;//只要CPU碰到return,此函数立马返回//
}
int read(void)
{
int a=250;
a++;
a+=250
return a;//有返回值,但是若不添加return,将返回一个随机数
}
int main(void)
{
int a=1,b=1,c=1,d=1;
//查看main函数中的地址和函数中的地址是否相同,
printf("abcd的地址为%p,%p,%p,%p\n",&a,&b,&c,&d);
// 打印,形参和实参内存情况如下图
print(a,b,c,d);
printf("read的返回值为:%d\n",read());
return 0;
}
注意:形参就是实参的一份拷贝,实参传递至形参时,拷贝一份。
说明:数组和参数最重要的区别在于传递地址;
/*定义访问数组的函数*/
void 函数名(数组的首地址,数组的长度)
{
可以查看数组元素;
可以修改数组元素;
}
案例1: 说明数组与函数关系
#include
void print_array(int a[],int length)//a[]为数组首地址
{
for(int i=0;i<length;i++){
printf("%d\n",a[i]); //数组元素可直接使用
}
printf("%d\n");
return;
}
void change_array(int a[],int length) //同理
{
for(int i=0;i<length;i++){
a[i] *=10;
}
return;
}
int main(void)
{
int array[5]={1,2,3,4,5};
/*调用print_array 函数打印数组元素值*/
//二维数组的sizeof(array)表示空间大小
print_array(array,sizeof(array)/sizeof(array[0]));
change_array(array,sizeof(array)/sizeof(array[0]));
return 0;
}
案例2: 实现数组元素内容交换
- 定义两个元素的数组,利用函数将这两个元素互换
- 利用函数将数组中某个元素的第n位清零
- 利用函数将数组中某个人元素的第n位置零
#include
extern void swap(int a[],int length);
/*定义交换数组的数据,可定义任意两个元素的交换*/
void swap(int a[],int length)
{
int c=a[0];
a[0]=a[1];
a[1]=c;
return;
}
/*将数组的某一个元素的位清零*/
void clear_array_bit(int a[],int index, int n)
{
a[index] &=~(1<<n);//与非清零 //a[index] |=(1<
return;
}
int main(void)
{
int a[2]={1,2};
printf("打印%d%d",a[0],a[1]);
swap(a,sizeof(a)/sizeof(a[0]));
printf("打印%d%d",a[0],a[1]);
clear_array_bit(a,3,1);//将数组的第三个元素的,第 1 位清零
return 0;
}
七、作用域与可见性
说明:按照作用域【范围】可见性【生命周期】来分:
- 局部非静态变量
- 局部静态变量
- 全局非静态变量
- 全局静态变量
定义: 定义在函数内部
void A(void)
{
int a=250;//此为局部变量
}
定义: 定义为函数之外的变量
int g_b=520;//全局变量
void A(void)
{
int a=250;//此为局部变量
}
int g_c=521;//全局变量
形式一:局部非静态变量
1. 定义:static关键字:如果定义变量前面加static关键字修饰,表明为静态变量;
2. 变量使用范围:从定义的地方开始,从定义的地方开始一次向下直到最近的花括号结束;
3. 内存生命周期:从定义的地方, *** 作系统会给变量分配内存,直到最近的花括号, *** 作系统会立马收回变量的内存;
4. 函数形参:void A(int a); //a在整个函数体都可以用,出了函数就不能用,以下代码说明:
形式1:
void A1(int c)
{
printf("a=%d\n",a);//不可以,报错,gcc编译时报没有定义的错误
int a=250;//定义 局部非静态变量
printf("a=%d\n",a);//可以
print("c=%d\n",c);//c变量只能在函数内部使用,不允许在main函数使用
}
形式2:
void A2(void)
{
if(1){
int a=250; //此变量的作用域为最靠近的花括号{}之内,出了范围就消亡
printf("a=%d\n",a);//可以
}
printf("a=%d\n",a);//不可以,报错,gcc编译时报没有定义的错
}
int main()
{
A1(23);
A2();
return 0;
}
形式二:局部 静态变量 (钉子户)
1. 变量使用范围:从定义的地方开始,从定义的地方开始一次向下直到最近的花括号结束;
2. 内存生命周期:定义的地方开始分配内存直到程序结束;一次分配,程序不结束下一次不会分配内存,接着上一次的用;/重要程序不结束,下一次就不会重新分配内存;
void A1()
{
static int a=250;//定义 局部静态变量
printf("a=%d\n",a);//可以
a= 10;
}
int main(void)
{
A1();//输出a=250
A1();//不会再给 static int a 分配内存,相当于语句不执行,接着上次使用,a=10;
return 0;
}
形式三:全局 非静态变量
1. 在同一源文件
1. 变量使用范围:全局非静态变量的定义和使用访问都是在同一个文件
2. 内存生命周期:定义的地方开始分配内存直到程序结束;
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);//可以,函数内部访问全局非静态变量
}
2. 在不同源文件
1. 明确:如果一个源文件定了一个全局非静态变量,另外一个文件想要直接访问这个全局非静态,只需要extern 声明这个全局非静态即可
2. 语法:声明全局非静态变量的语法:extern 数据类型 全局非静态变量名;
3. 结论:一旦声明,就可以访问别的文件定义好的全局非静态变量。
4. 切记:变量使用范围分两种情况:
- 如果本文件访问,范围为定义的地方开始向下可以访问,前面的不可以;
- 如果是不同文件(跨文件)之间访问,范围是声明的地方依次向下所有的函数都可以访问;
- 此变量生命周期:从启动运行程序时, *** 作系统就会分配内存;知道程序结束, *** 作系统回收。
- 切记:全局非静态变量实际开发时少用,慎用,避免出现乱序,一定记得互斥访问保护,但是降低执行效率。
//*全局非静态变量:同一个文件*//* vim func1.c *//
#include
/*定义全局非静态变量*/
int g_a=250;
void A(void)
{
printf("A函数:g_a=%d\n",g_a);
}
void B(void)
{
g_a++;
}
*vim func2.c*
#include
extern void A(void);
extern void B(void);//由于跨文件访问函数,故调用前需要声明才行
extern int g_a;//由于跨文件访问变量,故调用前需要声明才行
int main(void)
{
A();//打印250
B();//变量自加1
A();//打印251
printf("g_a=%d",g_a);
return 0;
}
/最后执行 gcc -o func1 func1.c func2.c
形式四:全局 静态变量
- 全局 静态变量的定义和使用访问都是在同一个文件
- 全局静态变量只能用于本文件,其他源文件不可访问;
- 能降低乱序的可能性;
- 只能用于定义变量的文件中,而且从定义的地方开始。
- 生命周期:启动程序开始,分配内存,直到结束再将内存收回。
- 少用、慎用,迫不得已,互斥访问,但是比全局非静态发生乱序的现象要小;
// vim var.c
#include
void B(void)
{
printf("g_a=%d\n",g_a);//不可以,gcc报没有定义的错误
}
static int g_a=10;//定义初始化为全局静态变量,只从定义的地方开始,到程序结束;
void A(void)
{
printf("g_a=%d\n",g_a);//可以,函数内部访问全局非静态变量
}
static void C(void)//vim var1.c无法访问此函数
{
g_a--;
}
/vim var1.c
#include
extern void B(void);//声明函数A
extern void A(void) ;//声明函数B
extern g_a; //声明全局变量g_a,报错
int main(void)
{
B();
A();
C();//报错
return 0;
}
gcc -o var var.c var1.c
总结
- static修饰的全局变量只能用于本文件,其余文件不允许。
- static 修饰的函数只能用于本文件,其他文件不能访问。
- static 的变量和函数用起来 相对安全,间接保护,降低乱序发生概率
- 抢夺CPU能力:A程序
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)