第九章 函数进阶

多函数程序的执行过程

见图k

k

变量的作用域和生存期

  • 代码示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
void main()
{
int num1 = 99;
{//代码块
int num2 = 199;
printf("%d\n",num1 + num2);
}
printf("%d\n",num1 + num2);
}
/*
报错:
error:'num2'undeclared(first use in this function)
错误:变量num2没有被声明(在函数中第一次使用)
*/
  • 注意:

    1、变量只存在于定义他们的语句块中

    2、变量在一个块内声明时创建,在这个块结束时销毁-自动变量

作用域

  • 代码示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
void main()
{
int count1 = 1;
do{
int count2 = 0;
count2++;
printf("count=%d\tcount2=%d\n",count1,count2);
}while(++count1 < 5);
printf("count1 = %d\tcount2 = %d\n",count1,count2)
}
/*
变量的作用域决定了变量的可访问性
思考:
如果将变量count1和count2都改为count,输出结果会一直循环count = 1
因为while(++count < 5) //是外部count
*/

局部变量

1
2
3
4
5
6
7
8
9
10
11
12
void changNum()
{
int num1 = 5,num2 = 8;
num1 = 155;num2 = 288;
}
void main()
{
int num1 = 5,num2 = 8;
changeNum();
printf("num1=%d,num2=%d\n",num1,num2);
}
// num=5,num2=8

全局变量

1
2
3
4
5
6
7
8
9
10
11
12
int count = 0;
void changeNum()
{
count++;
}
void main()
{
count++;
changeNum();
printf("count = %d\n",count);
}
// count = 2

变量的存储类型

存储类型说明符 存储类型 说明
auto 自动存储 只能用于块作用域的变量声明中,局部变量默认情况下归为自动存储类型
register 寄存器存储 只用于块作用域的变量,请求速度快。对于循环次数较多的循环控制变量及循环体内反复使用的变量均可定义位寄存器变量
static 静态存储 载入程序时创建对象,程序结束时对象消失
extern 外部变量 说明符表示声明的变量定义在别处。作用域是整个程序,生存期贯穿应用程序的开始和结束

变量的存储类型示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
void report_count();
void counter(int num);
int count = 0;//文件作用域,外部链接
int main()
{
int value;//自动变量
register inr i;//寄存器变量
printf("请输入任意数字,0退出:");
while(scanf("%d",&value) == 1&& value > 0)
{
count++;
for(i = value;i >= 0; i--)
counter(i);
printf("请输入任意数字,0退出:");
}
report_count();
}
void report_count()
{
printf("循环执行了%d次\n",count);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
extern int count;//引用式声明,外部链接
static int total = 0;//静态定义,内部链接
void counter(int);//函数原型

void counter(int num)
{
//局部静态变量
static int subTotal = 0;
if(num <= 0)
{
printf("第%d轮循环执行完毕\n",count);
printf("局部静态变量subTotal和全局静态变量total:\n");
printf("subTotal:%d\ttotal:%d\n",subTotal,total);
subTotal = 0;//每次内循环结束后重置为0
}
else
{
subTotal += num;
total += num;
}
}

传值调用

传值调用的机制

  • 按值传递
    • 给函数传递变元(参数)时,变元(参数)值不会直接传递给函数,而是先制作变元(参数)值的副本,存储在线上,再使这个副本可用于函数,而不是使用初始值

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
void change(int);
int main()
{
int num = 9;
change(num); //num = 9
printf("num = %d\n",num);
}
void change(int num)
{
num++; //num = 10
}
  • 引用传递
    • 指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
void change(int *);
int main()
{
int num = 9;
change(&num);
printf("num = %d\n",num);
}
void change(int *num)
{
*num += 1;
}

使用数组作为函数参数1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#define N 5
void input(double []);//录入元素
void sort(double []);//排序
void show(double []);//显示元素
void main()
{
double scores[N];
input(scores);//不需要&
show(scores);
sort(scores);
printf("排序后:\n");
show(scores);
}
1
2
3
4
5
void input(double scores[])
{
printf("请输入%d个同学的成绩:\n",N);
//循环录入数组元素
}
1
2
3
4
5
void sort(double scores[])
{
double temp;
//冒泡排序
}
1
2
3
4
5
void show(double scores[])
{
printf("语文\t英语\t数学\t物理\t化学\n");
//循环显示数组元素
}
  • 注意:

    1、数组作为函数实参时,只传递数组的地址(首地址),并不传递整个数组的空间

    2、当用数组名作为实参调用函数时,数组首地址指针九被传递到函数中

使用数组作为函数参数2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
int count = 0;
//查找某个值在数组中的下标
int find_index(int *,int);
void mian()
{
int nums[] = {1,2,34,55,3};
int searchNum;//要查找的数字
count = sizeof(nums) / sizeof(nums[0]);
printf("请输入要查找的数字:");
scanf("%d",&searchNum);
int index = find_index(nums,seachNum);
printf("所查找数字的下标为:%d\n",index);
}
1
2
3
4
5
6
7
8
9
10
11
12
int find_index(int *p,int num)
{
int index = -1,i = 0;
for(;i < count;i++)
{
if(*(p + i) == num)
{
return i;
}
}
return -1;//没有找到就返回-1
}

使用头文件

  • 自定义头文件
    • 一般放一些重复使用的代码,例如函数声明,变量声明,常量定义,宏的定义等
1
2
3
4
5
6
#ifndef MYHEADER_H_INCLUDED
#define MYHEADER_H_INCLUDED

//代码部分

#endif // MYHEADER_H_INCLUDED
  • 注意:

    1、MYHEADER_H_INCLUDED为一个唯一的标号,命名规则跟变量的命名规则一样,常根据它所在的头文件来命名

    2、代码含义:如果没有定义

    MYHEADER_H_INCLUDED,则定义

    MYHEADER_H_INCLUDED,并编译下面的代码部分,直到遇到#endif

更新于

请我喝[茶]~( ̄▽ ̄)~*

Chen 微信支付

微信支付

Chen 支付宝

支付宝

Chen 贝宝

贝宝