函数
函数调用
每一个应用程序都有函数表,每个表格存储函数的地址,改变地址可以改变行为
不允许在一个函数内部再定义一个函数
当函数值为整型时,可以省略,因为默认是int类型
main(){}—省略返回值
通过栈来实现函数的执行
副本机制
函数的副本机制—函数的内部变量—实参和形参,参数的传递是单向传递
C语言传参的时候应该尽量保证类型一致,参数个数一致,如果不对,c语言不保证结果正确
int add(int a, int b)//隐含赋值操作int a = 2.4,赋值会自动进行类型转换/return也会完成类型转换,return也有副本机制,会保存在内存/寄存器中(编译器决定),可用于循环内部结束循环
add(2.4,3)
&add(1,2)—右值计算,return有副本机制,会保存在内存/寄存器中,而寄存器无法获取地址,因此不对,所以函数的调用不能取地址
函数的参数除了数组,都是副本
如何学习常用的函数并且掌握
函数参数运算顺序(存疑,需要复习)
Add(a, a++) 从右往左计算,假设a=5,那么输入是(6,5)
如果是调用的时候参数多了,如add(1,2,3)压栈是从右往左:
1
2
3
出栈顺序是1,2第三个数值不会被调用
可变参数:
- 形式:void showint(int start, …)
- va_start(argp, start);//从首地址开始,读取start后面的数据,argp是一个char *类型
- argvalue = va_arg(argp, int) 读取 写入到另外一个变量里边,按照int进行读取
- 结束:va_end(argp);
全局变量和局部变量
全局变量,没有赋值,默认为0;声明可以有多个,但是定义只能有一个
(1)main函数内的变量不是全局变量,而是局部变量。
(2)只不过它的生命周期和全局变量一样长而已。
(3)全局变量一定是定义在函数外部的。
(4)全局变量可以跨文件调用
局部变量,没有声明和定义的区别,只有定义
当局部变量和全局变量有相同变量名,局部变量会覆盖全局变量,在局部变量所在的块或者函数内,对变量的操作不影响全局变量的值,全局变量不起作用,在局部变量所在的代码块或函数外部,全局变量才起作用。
函数声明和定义的差别
- 声明是不开辟内存的,仅仅告诉编译器,要声明的部分存在,要预留一点空间。定义则需要开辟内存。
- 在局部函数中只有定义,没有声明。
- 局部函数的变量,一旦返回,变量就会被销毁,内存就会被回收,如果是全局变量不会回收。
数组
数组没有副本机制,如果数组作为参数进行传递,那么会退化为指针。
数组名是一个常量
编译和链接
寄存器变量
Register int a;表示寄存器变量,对于频繁调用的变量vc编译器会自动优化为寄存器变量,但是对于gcc并不会自动优化。C语言不可以获取寄存器变量的地址,但是C++是可以的,因为对变量进行了备份。
全局变量和静态变量不要放在寄存器,寄存器数量有限
函数指针(需要复习)
函数指针赋值:void (*p)() = func; 函数指针可以存储不同函数的地址,执行不同的代码块
劫持
一个进程不能改变另一个进程的内存
改变一个变量需要一个指针,改变一个指针需要一个二级指针
劫持自己
劫持他人
劫持系统