1.非类类型的函数返回值的接收方式:
(1)小于4字节:eax寄存器接收。
(2)大于4字节小于8字节:eax寄存器和edx寄存器配合接收。
(3)大于8字节:由调用方从被调用方的数据拷贝而来(副本),再由临时变量带出。
2.const的用法:
(1)除声明以外一定要初始化,修饰的是常量,不可由普通指针指向。
(2)修饰的是直接右边,例如:const int *p=&a; *p=22;后一句就是不对的,*p不可修改
(3)处理方式:在编译阶段就把要用到的常量替换成初始化时的值,之后的修改都无法改变(即使对应地址上的值被修改)
(4)const修饰的全局变量为local属性(符号解析时只关心全局属性的变量)
(5)extern可以把local属性的符号改为global属性的符号(对全局变量而言)
3.函数的默认值:
(1)默认值一般写在声明中,赋默认值的由右向左依次赋值,避开默认值的二义性
int add(int a,int b,int c);
int sum(int a,int b=0;int c=9);//以上两种正确,调用时只需要传没给默认值的参数值
int equal(int a,int b=0;int c);//错误
(2)默认值只能赋值一次;
(3)限制条件:可以用(静态)全局变量,也可以是函数调用(先声明后使用);
int gdata = 10;
static int gdata1 = 30;
int Sum(int a, int b)
{
return a + b;
}
int Func(int a, int b, int c = gdata);//用全局变量做默认值
int Func(int a, int b = Sum(gdata,gdata1), int c=0);//函数调用做默认值
4.函数重载:
(1)函数符号生成规则(支持函数重载):由函数名,返回值,参数列表(参数个数,参数类型,参数顺序)
(2)要素:同作用域;函数同名;参数列表不同;
//实际上真正支持函数重载的就是函数参数列表(参数个数、类型、顺序)
int Max(int a, int b); //?Max@@YAHHH@Z
double Max(int a, int b); //?Max@@YANHH@Z
double Max1(int a, int b); //?Max1@@YANHH@Z
double Max1(int a, double b); //?Max1@@YANHN@Z
int Max(int a, int b) //之所以可以重载是因为生成符号时因函数返回值,参数列表不同而不同
{
return a > b ? a : b;
}
double Max(double a, double b)
{
return a > b ? a : b;
}
char Max(char a, char b)
{
return a > b ? a : b;
}
char* Max(char* a, char* b)
{
return strcmp(a, b) > 0 ? a : b;
}
int Sum(int a, int b)
{
return a + b;
}
double Sum(int a, int b)
{
return a + b;
}
(3)注意:函数不能同时做默认值和函数重载
(4)函数末尾加const变为常函数也是一种重载形式。
5.内联函数inline:
(1)修饰函数但是不生成符号,在调用点展开,在堆栈调用空间大于代码展开空间时使用可以节省空间。为方便使用,一般写在头文件中。
(2)类似宏处理但是内联函数的处理是在编译阶段,因此存在类型检查,较宏替换来说更加安全。
(3)缺点:代码膨胀容易造成空间浪费,是一种用空间换时间的做法。
(4)注意事项:内联函数只是给编译器的一个建议,采不采用根据堆栈调用和内联函数孰优孰劣来决定。对于switch,while,递归而言无效。内联函数只在可调式版本下生效,在发行版本下无效。内联函数基于实现而不是基于声明,放在声明出无效。
(5)内联函数与static区别:前者修饰的是全局属性函数,后者则是局部属性的;前者不生成符号,后者则会生成;前者不存在堆栈调用,后者存在。