认识函数:
1.使用一直语言实现时,应该了解它提供哪些库,如库函数,类库,系统调用等。尽量使用库函数,避免重复劳动
2.静态链接库:连接器会从相应的库中提取这些函数的实现代码把她们链接到你的程序中,若没有调用,连接器是不会把实现代码链接进来的。
动态链接库:DDL 运行时将所有的DDL都复制到运行环境的相应目录下。
注意:我们在开发一些通用类的时候,应该设计并实现完整的功能,而不许要去担心它的使用者会因为仅仅使用其中的一小部分功能却要包含整个文件导致代码体积增大。
函数调用:
用实参来初始化形参,而不是替换形参。应该在原型中写出形参名称,虽然编译器会忽略它们,这样做使函数具有“自说明”和“自编档”能力。
调用方式:过程调用,嵌套调用,递归调用。 回调函数
回调函数:事件驱动程序and多线程应用程序中很常见。典型例子:系统定时器回调函数和线程函数
特点:线程函数不使用普通的函数堆栈,而使用线程自己的堆栈,线程堆栈是线程在每次启动时动态分配的,这就可以在每次使用时使用不同的堆栈,从而避免线程函数执行流重叠时出现的一些堆栈破坏。此外,若一个函数可能被多个线程调用的话,对于他们共享的数据进行同步访问,避免使用static局部变量。
函数堆栈:
函数堆栈使用的是程序的堆栈段内存空间,虽然程序的堆栈段是系统系统为程序分配的一种静态数据区,但是却是在调用到它的时候才动态分配。
不能在编译时为函数分配好堆栈 1 因为无法在编译时确定一个函数运行时所需的堆栈大小 2 函数调用完毕不释放内存导致内存浪费
堆栈是自动管理的,即局部变量的创建和销毁,堆栈的释放都是函数自动完成的,不需要程序员的干涉。这就是堆栈与堆和自由存储空间的区别(能否显式的分配和释放)。
函数堆栈的三个用途:在进入函数前保存环境变量和返回地址,在进入函数时保存实参的拷贝,在函数体内保存局部变量。
函数调用规范:
决定了函数调用的实参压栈,退栈及堆栈释放的方式,以及函数名改编的方案。
1.——caecl:C++/c函数默认调用规范,参数从右往左依次传递压入堆栈,由调用函数负责堆栈清退,该方式利于传递可变参数给被调用函数,因为只有调用函数才知道它应该给被调用函数传几个参数),比如printf()
2.——stdcall:Win API函数使用的调用规范,参数从右往左依次传递压入堆栈,由被调用函数负责栈的清退,生成的函数代码比_caecl更小,当有可变参数时自动转为_caecl规范。
3.——thiscall:C++非静态成员函数调用方式,不能使用个数可变的参数,当调用非静态成员函数时,this指针直接保存在ECX寄存器中而非压入函数堆栈。其他的与_stdcall相同。
4.——fastcall:该规范所修饰的函数实参将被直接传递到CPU寄存器中,而非堆栈,这就是快速调用的含义,堆栈请退由被调用函数负责。不能用于成员函数。
函数必须指定一个调用规范,否则会出现编译错误。
参数传递规则:
1.传值调用,2传址调用 3.引用传递
规则1:函数原型定义明确写出每个参数的类型和名字,若函数没有参数,应使用void不要空着,因为标准C把空的参数列表解释为可以接受任何类型和个数的参数,标准C++则把空的参数列表解释为不可以接受任何参数。移植时需要注意!
规则2:参数命名要恰当,输入参数输出参数的顺序要合理,避免参数过多,可以考虑用对象封装
规则3:若参数为指针,只做输入用,应该加const,防止修改。
返回值的规则:
规则1:不要省略返回值类型,标准C省略默认返回int,容易误解为void C++明确必须有返回值类型
规则2:函数名字与返回值类型在语义上不可冲突,char c=getchar();//error int getchar(void)
规则3:有时候函数原本不需要返回值,但是为了增加灵活性,支持链式表达,char *strcpy(char* strDest,char* strSrc), strlen(strcpy(str,"helloworld"));
规则4:返回值是一个对象,可以返回引用替换返回对象值,提高效率,支持链式表达0
函数的内部实现规则:
函数入口:对参数的有效性进行检查。使用断言assert来防止此类错误
函数出口:对return 语句的正确性和有效性进行检查。
不能返回局部变量的地址和引用。
返回临时对象:避免构造析构函数的开销,提高了效率
返回临时变量: return (x+y);而不是 temp=x+y;return temp;