4-8-实参与形参、函数声明与定义、函数读取顺序、可变参数的函数、函数生存周期
来源:互联网 发布:linux应用层 编辑:程序博客网 时间:2024/05/18 18:03
学习4-8期视频笔记
1、 形参与实参
//函数调用前,形参,也就是函数定义时()中的参数,值都不确定
//不确定的值,不会分配内存,只有调用函数的时候,才会新建一个变量
//接受实际参数的值,当函数调用结束时候,形参占据的内存会被回收
//实际参数是函数调用的时候,函数传递过来的确切值就是实际参数
//实际参数可以是常量,变量或者表达式
//形参与实参内存地址不同,占用不同的内存空间
#include<stdio.h>#include<stdlib.h>
void go(int num) //int num 是一个形参,只有调用的时候,才会分配一个内存,函数调用的时候,形/参分配内存,新建一个变量,存储传递过来的实参{ num = 100; printf("\ngo=%d %x", num,&num);}void main(){ int num = 10; printf("num=%d %x", num,&num); //num=10 go(num);//num=100 go(3+5); //num=100 printf("\n num=%d %x", num, &num);//num=10 system("pause");}
实参给形参赋值,会自动进行数据据类型转换
2、 局部变量与全局变量
#include<stdio.h>#include<stdlib.h>inty=40;//全局变量,不属于任何一个函数,可被任何一个函数调用//局部变量调用完成,会被回收void go(){ int x = 100; //x为局部变量,只可以在该函数内使用 printf("\nx=%d %x", x, &x);}void main(){ go(); //printf("num=%d%x", x, &x); //因为x为局部变量,这里不能输出x的地址和数值 system("pause");}
变量是全局变量还是局部变量,看变量声明的位置
同名情况,局部变量会屏蔽全局变量(后来者居上),c++中可以通过(::+变量名) 访问全局变量
块语句内部变量,作用域是整个块
全局变量生存周期很长,一直占用内存,除非程序退出
缺点:容易与局部变量重名,很容易被屏蔽,失效。值容易被修改(注入)
注意:1、名字要容易理解,尽量不与局部变量重名
2、 避免占用内存较大的变量使用全局变量,节约内存
3、 避免全局变量被错误的修改
正规的软件工程,写一个函数要修改全局变量,一定要注释(哪块修改,修改为什么值)
全局变量没有初始化,会默认为0
3、 函数的声明和定义
同名定义只可以有一个,但是声明可以有多个。
函数在调用之后,c可以不声明,c++必须声明
c语言编译比较宽泛,有库的路径,可以自动定位,不需要函数的生命;
c++比较严谨,必须声明函数声明、库文件、头文件。
c语言,没有函数声明,有库可以调用;没有函数声明有函数实体,可以调用
c++,没有函数声明,有库不可以调用;没有函数声明有函数实体,实体在调用前可以调用,在调用后不可以调用
全局变量可以有多个(三个int a;但是不能有赋值),这时候系统会将其当作声明处理。
4、 函数
(1)函数定义在程序中是平行的,即不允许在一个函数内部再定义一个函数;
(2)函数名是用户自定义标识符,当函数值为整型时类型名可省略(不推荐省略);当函数不需要向调用处返回值时,使用void类型名
(3)形参表中的形参是用户自定义标识符,没有参数时,圆括号不能省略,此时函数为无参函数
#include<stdio.h>#include<stdlib.h>int add(int a,int b) //这里int a,int b只有调用的时候才会分配内存,函数运行完后会自动释放{ a = 1; b = 2; return a + b;}void main(){ int a = 10; int b = 20; printf("%d", add(a, b));//函数参数除了数组以外,其他都是副本//c语言参数过多会警告,但会忽略多的,结果也不保证正确 system("pause");}
//结果为3
注意:(1)如果函数类型为void以外的任何一种类型,则函数内部必须出现return语句
(2)return语句中表达式的类型应与函数值类型一致。若不一致,以函数值类型为准
函数调用不能取地址
5、 函数参数读取顺序
#include<stdio.h>#include<stdlib.h>void show (int a,int b){printf(“a=%d,b=%d”,a,b)}void main(){inta=5;show(a,a++);}
//结果为a=6,b=5
//因为栈为先进后出,c语言是从下往上,从后往前压入栈中(这样才能保证顺序执行),所以这个调用函数内部是从右往左执行
6、 可变参数的函数
//第一个参数为总个数
//加法
#include<stdio.h>#include<stdlib.h>#include<stdarg.h>int add(int num,...)//随意输入多少个数相加{ int res = 0;//结果 va_list argp;//存储参数开始的地址 va_start(argp, num);//从首地址开始,读取num后面的数据 for (int i = 0; i <num; i++) { res +=va_arg(argp,int);//读取一个数据按照int型解析 } va_end(argp);//结束读取 return(res);}void main(){ printf("%d\n", add(3, 1, 2,3));//第一个值为后面参数的个数,后面为具体数值 printf("%d\n", add(4, 2, 2,3,5)); printf("%d\n", add(5, 1, 2,3,4,5)); system("pause"); }
//运行多个程序
#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<stdlib.h>#include<stdarg.h>void go(int num,...){ va_list argp;//存储参数开始的地址 va_start(argp, num);//从首地址开始,读取num后面的数据 for (int i = 0; i < num; i++) { char str[50]; sprintf(str,"%s",va_arg(argp,char*));//读取一个数据按照int型解析 system(str); } va_end(argp);//结束读取}void main(){ go(3, "notepad","calc", "tasklist"); system("pause"); }//未知个数的输出
//以-1结尾,表示输出结束void showint(int num, ...){ va_list argp;//存储参数开始的地址 va_start(argp, num);//从首地址开始,读取num后面的数据 int argvalue = num; do { printf("%d", argvalue); argvalue=va_arg(argp, int);//读取一个数据按照int型解析 } while (argvalue != -1); va_end(argp);//结束读取 }void main(){ showint(1, 2, 3, 4, -1); system("pause");}
7、 递归
//打开notepad
void main(){ system("<strong>start</strong> notepad");//并行打开无数个notepad main();}
//通过给目标程序注入dll使程序栈溢出
#include<Windows.h>_declspec(dllexport) void go(){Sleep(1);go();}
//叠加从0-num
int add(int num){if(num==0){printf(“%d”,sum)}else{returnnum+add(num-1)}}
例子
树状递归 f(n)=f(n-1)+f(n-2)
线性递归 f(n)=f(n-1)+n
树状递归速度很慢,递归很慢,函数调用返回都需要时间(进栈出栈)
递归=循环+栈
int getn(int num)//递归{if(num==1||num==2){return1;}else{returngetn(num-1)+getn(num-2);}}int getN(int num){ //循环 if(num==1||num==2)return 1; else{ intf1=1; intf2=1; intf3; for(inti=3;i<=num;i++){ f3=f1+f2; f1=f2; f2=f3; } } returnf3;}
8、 函数参数的生存周期
函数返回值有副本机制,返回时会另保存一份
printf(“%d”,add(1,2))l//这里打印的就是副本,内存中的数据就会被销毁
返回值(临时变量)存储在寄存器,原数据被销毁,返回副本数据(寄存器中的数据)
返回值如果是全局变量,则不会被回收
- 4-8-实参与形参、函数声明与定义、函数读取顺序、可变参数的函数、函数生存周期
- 函数声明与函数定义的参数
- 函数的类型,函数的声明,函数的定义,函数的调用,函数嵌套,函数递归,形参实参
- 函数的定义声明 用法 形参实参 return关键字
- [Python] python中函数的参数定义与可变参数
- 函数定义与声明
- C语言函数入栈顺序与可变参数函数
- C语言函数入栈顺序与可变参数函数
- C语言函数入栈顺序与可变参数函数
- C语言函数入栈顺序与可变参数函数
- C语言函数入栈顺序与可变参数函数
- C语言函数入栈顺序与可变参数函数
- C语言函数入栈顺序与可变参数函数
- C语言函数入栈顺序与可变参数函数
- 函数分类、函数声明和定义、函数调用,形参实参、函数嵌套调用
- 《IOS_C语言》函数分类、函数声明和定义、函数调用、形参实参、函数嵌套调用
- 参数可变的函数定义
- C++构造函数—构造函数的声明与定义、带参数的构造函数
- a 标签中调用js的几种方法
- SQL——link操作
- 【HDU】5751 Eades【FFT】
- 第十四节上篇:正则表达式及其他常用类(个人总结)
- 一秒会用优先队列(学习)
- 4-8-实参与形参、函数声明与定义、函数读取顺序、可变参数的函数、函数生存周期
- 链接<a>执行JS
- vim 或者vi 删除每行最后一个字符
- Xcode7 真机调试(无需证书)详解
- Spark-理解RDD
- vs2015编译libcurl+ssl+zlib(MT静态版)
- Unity游戏设计模式(三)原型模式(Prototype Pattern)
- [6] ffmpeg + SDL2 实现的视频播放器「视音频同步」
- 2016/09/17 将一个字符串翻转