第三章:简单函数
1.数学函数(301.c)
1.Sin(pi/2)中sin是函数,sin(pi/2)是函数调用,函数调用也是一种表达式,这个表达式由函数调用运算符(也就是括号)和两个操作数(sin,pi/2)组成,这个表达式的值就是我们称的函数返回值,
2.Printf(“sin(pi/2)=%f\nlnq=%f\n”,sin(pi/2),log(1.0));printf也是一个函数,这个语句中有三个参数,第一个参数是格式化字符串,是字符串类型的,第二个和第三个参数是要打印的值,是浮点型的。整个printf是一个函数调用,也就是一个表达式。它的返回值,表示实际打印的字符数,我们用printf不是为了用它的返回值,而是为了利用它所产生的副作用(Side Effect)
3.Side Effect:这个概念适用于运算符组成的表达式,比如:a+b这个表达式也可以看与一个函数调用,运算符+是一个函数,它的两个参数是a 和b,返回值是两个参数的和,传入两个参数,得到一个返回值,并没有产生任何Side Effect。而如果把a=b这个表达式看成函数调用,传入两个参数a 和b分别做左值和右值使用,返回值就是所赋的值,即b的值也是a 的值,但除此这外还产生了一个Side Effect,就是a的值改变。
4.在编译时gcc main.c –lm,因为数学函数位于libm.so库文件中(通常在/lib目录下),-lm选项告诉编译器,程序中要用的数学函数要到这个库文件中去找,平时我们用的绝大部分库函数位于 libc.so库文件中,使用libc中的库函数在编译时不需要加-lc,因为这个选项是gcc默认的。
2.自定义函数
1.Main函数是被操作系统调用的,它的返回值是返回给操作系统看的,程序执行成功返回0,在执行过程中出错返回非0值
2.Echo $? :$?是shell中的一个特殊变量,表示上一个运行结束的程序的退出状态
3.函数的调用执行顺序(owndefine.c)
4.函数声明、函数定义、函数原型
上例中:void threeline(void)这一行,声明了一个函数的名字 ,参数类型和个数,返回值类型,这称为函数原型。在代码中可以单独写一个函数原型,后面加;号结束,而不写函数体。这种只能叫函数声明而不能叫函数定义。只有带函数体的声明才叫定义
5.编译器只有见到函数定义才会生成指令,而指令在程序运行时当然也是要占存储空间的,那么没有函数体的函数声明有什么用呢?它为编译器提供了有用信息,编译器在处理代码的过程中,只有见到函数原型(不管带不带函数体)之后才知道函数的名字、参数类型和返回值,然后在碰到函数调用时才知道怎么生成相应的指令。所以函数原型必须出现在函数调用之前。这也是我们所说的“先声明后使用”的原则。
3.形参与实参 main函数的变量h,与print_time函数中的参数hour是两个不同的变量,只不过它们各自的存储空间中存了相同的数值,因为变量h的值赋给参加hour(302.c)
4.局部变量与全局变量(304.c)
1.某个函数中定义的变量不能被另一个函数使用,即使在两个函数中的变量名是相同的,数值相同,但他们仍然是不同的变量,代表不同的存储空间,只不过是各自的存储空间的值是相同的。
2.每次调用函数时局部变量都表示不同的存储空间,局部变量是在每次函数地分配存储空间,每次函数返回时释放存储空间。(306.c)
3.全局变量定义在所有的函数体外,它们在整个程序开始之前分配存储空间,在程序结束时释放存储空间,所有函数都可以通过全局变量名访问它们。
4.如果全局变量与局部变量重名,在局部变量所在的函数中,调用的是局部变量,其它的调用的是全局变量。(305.c)
5.局部变量可以用任意类型相符的表达式初始化,而全局变量只能用常量表达式初始化
Double pi=3.14+0.0016 double pi=acos(-1.0)全局变量后面一个是错了
全局变量的初始值要求保存在编译生成的目标代码中,所以必须在编译时就能计算出来,,然而后一种必须在生成了目标代码之后在运行时调用acos函数才能知道,所以不能用来初始化全局变量。
6.如果全局变量在定义时不初始化,则初始值:整型是0,字符型是‘/0’,浮点型是0。0,如果局部变量在定义时不初始化,则初始值不确定. (306.c)