1. 函数(不能嵌套定义)
(1)C 程序的框架
- 单框架:由一个 main() 函数所组成。
- 复合框架:由一个 main() 函数和若干个子函数所组成。
(2)函数的分类
- main() 函数也称主函数,是 C 语言程序的入口,该函数在 C 程序中必不可少。常见的使用方式有两种:有返回值 int main() 和无返回值 void main()。
- 无参函数和有参函数。例如:无参函数 int sort( ),有参函数 int insert(int num)。还包括一些库函数,例如:sqrt、sins 等。
- 库函数。常见的库函数有:printf、scanf、gets、puts、getchar、putchar、sqrt 、srtcmp、strcpy 等等。
- 用户自定义函数即根据问题所需,自己所定义的函数。例如:int add( ),int sum(char str)。
(3)函数的定义
- 函数体可以没有语句,但不可没有中括号 “{}”,函数名后必须有一对小括号 “()”。
- 不能在定义函数时在函数尾部小括号后直接跟分号 “;”,声明函数时函数尾部要加分号 “;”。
- 定义函数时,必须采用传统方式或现代方式指定形参的类型。
- 函数返回值类型有两种(有返回值,无返回值(void型)),如果是有返回值类型需用 return 语句返回该类型,无返回值类型则无需使用 return 语句。
/* 函数返回值类型 函数名(形参列表) 函数名遵循用户自定义标识符原则
{
函数体;
}
*/
//有参函数
int max( int a , int b )
{
if( a > b )
max_num2 = a ;
else
max_num2 = b ;
return max_num2;
}
//无参函数
int star()
{
int i ;
for( i = 0 ; i < 17 ; i ++ )
printf("*");
return 0;
}
(4)函数调用
- 非空(void)类型:变量名 = 函数名(实参列表)。
- 空 (void)类型:函数名(实参列表)。
注意:函数将实参列表数据传递给形参列表时,采用的是单向传值的方式,且在传值过程中遵循三一致原则:实参传给形参的参数个数相同、参数类型相同和参数的位置次序也保持相同。
//函数调用的代码展示
//非空类型,有参函数
int max( int a , int b )
{
if( a > b )
max_num2 = a ;
else
max_num2 = b ;
return max_num2; //返回最大值
}
int main()
{
int x = 117 ;
int y = 818 ;
int max_num1 ;
max_num1 = max( x , y ); //调用 max 函数,并返回最大值
printf("max_num1=%d",max_num1);
return 0;
}
//空(void)类型,无参函数
int star()
{
int i ;
for( i = 0 ; i < 17 ; i ++ )
printf("*");
return 0;
}
int main()
{
star(); //调用 star 函数
}
(5)函数使用例题分析(错误案例)
int main()
{
sum(3,5); //调用 sum 自定义函数
}
void sum(int x,int y)
{
printf("%d",x+y);
}
注意:上述求两个整数的和的代码无法正常运行。
解释:因为 main () 函数采用的查找方式是向上查找,而 main () 函数出现在 sum 自定义函数之前,向上查找无法找到 sum 自定义函数,所有该程序代码无法正常运行。
解决方法:第一种,将 main() 函数和 sum 自定义函数两者交换位置;第二种,采用原型函数声明语句声明 sum 自定义函数,例如:void sum(int x,int y);
修改后的代码示例如下:
//第一种解决方法
void sum(int x,int y)
{
printf("%d",x+y);
}
int main()
{
sum(3,5); //调用 sum 自定义函数
}
//第二种解决方法
void sum(int x,int y);
int main()
{
sum(3,5); //调用 sum 自定义函数
}
void sum(int x,int y)
{
printf("%d",x+y);
}
2. 函数中的变量
(1)变量三属性:变量定义的类型、作用范围(针对空间而言:局部变量和全局变量)、存储类别(针对时间而言:auto、static、register、extern)。
(2)定义类型:类型名 变量名列表 ; 例如:int x ; 、 float y ; 、char z ; (定义语句)
(3)作用范围:局部变量和全局变量
- 局部变量:定义在一个函数内部的变量。
- 局部变量只能在它所在的函数内部有效
- 不同函数中可以出现同名的变量,它们分别属于不同的变量
- 复合语句中定义的变量只能在此符合语句中有效
- 所有形式参数都属于局部变量
- 全局变量:定义在函数外部的变量
- 全局变量的有效范围是在本文件内从定义该变量的位置开始到本文件的结束
- 全局变量可以在它的有效范围内被每个函数引用
- 在同一个文件中若全局变量与局部变量同名,局部变量“屏蔽”全局变量,即优先使用局部变量
//变量的作用范围
#include <stdio.h>
int i = 5 ; // 定义全局变量,并初始化
int k = 10 ;
int main()
{
//定义局部变量
int i = 3 ;
int j = 4 ;
printf("i=%d",i); //局部变量 i 与全局变量 i 同名,屏蔽全局变量 i , 则输出 局部变量 i 的值:3
printf("j=%d",j); //输出局部变量 J 的值:4
printf("k=%d",k); //由于 main() 函数下没有局部变量 k,则此时输出 k 的值为全局变量 k 的值 :10
return 0;
}
(4)存储类别
- auto 类别变量
- auto 类别变量用完后释放所占空间
- 局部变量默认为 auto 类别变量,无初始化时,初值为随机值
- auto 类别变量使用时间短(生命周期短),又称临时性变量
- static 类别变量
- static 类别变量从定义到程序运行结束均占用存储空间
- 全局变量默认为 static 类别变量,五初始化时,初值为 0
- static 类别变量只进行依次初始化(生命周期长)
- register 类别变量(寄存器)
- register 类别变量只能是局部变量才能被说明
- register 类别变量一般不能直接使用
- extern 类别变量
- extern 类别变量可以加大变量的作用范围
- extern 类别变量的两种说明格式,第一种是定义时同时说明类别:存储类别 类型名 变量名 ; 。第二种是分别定义说明:类型名 变量名 ; 存储类别 变量名 ;
3. 预编译命令(独占一行)
(1)预编译命令:文件包含(include),采用 #include< > 或 #include “ ” 引用库文件。
(2)宏定义类型
- 无参宏定义: #define ,#define 宏名 宏内容
功能:用一个指定的标识符(宏名)来代表一串字符(宏内容),例如:#define PI 3,1415。
- 宏名一般用大写字母表示,遵循用户自定义标识符规则。
- #define 可在函数内外定义,但该命令应独占一行
- 在进行宏定义时,可以引用已经定义的宏名层层置换
- 进行宏替换时,必须先替换完所有的宏后在运算,同时替换过程不能乱加符号
- 带参宏定义:#define 宏名(参数列表) 宏内容 , #define s(x,y) x*y+3
功能:提供了一种更加灵活的替换方式
- 在定义有参宏时,参数列表必须用一对小括号括起,且小括号和宏名之间不能有空格
- 对有参宏名进行替换时,需将形参改为相应的实参,并且注意分清形参和实参的对应关系