,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,9.3 参数传递:数组作参数电子课件 计算机系统基础:C语言视角(RISC-V版),参数传递:数组名作参数,数组作为参数,在函数之间传递数组,问题:,把数组中的所有值从一个函数传递到另一个函数中,,花费大!,C,语言,:,传递数组名,(,数组的基址,),示例,:冒泡排序,将一个整数数组按升序排列,x0 x1x2xN-1,函数声明,1#include,2#define MAX_NUMS 10,3,4 void BubbleSort(int list,int);,5,“,”,参数是特定类型的数组的基址,void BubbleSort(,int*list,int);,函数调用,6 int main(),7,8int index;,9int numbers MAX_NUMS;,10,11,/*,获取输入,*/,12printf(Enter%d numbers.n,MAX_NUMS);,13for(index=0;index MAX_NUMS;index+),14,15printf(Input number%d:,index);,16scanf(%d,17,18,19,/*,调用排序程序,*/,20,BubbleSort(numbers,MAX_NUMS);,21,22,/*,输出已排序的数组,*/,23printf(nThe input set,in ascending order:n);,24for(index=0;index MAX_NUMS;index+),25printf(%dn,numbersindex);,26,27,numbers,数组的基址,等价于,&numbers0,类型,与,int*,类似,函数定义,28void BubbleSort(int,list,int n),29,30int i,j;,31int temp;,32,for,(i=1;i=n-1;i+),33,for,(j=1;j listj),35,36temp=listj-1;,37,listj-1,=,listj,;,38 listj=temp;,39,40,参数,list,:,&numbers0,list2:numbers2,*(list+2):numbers2,赋值运算符右边,取出该地址中的值,赋值运算符左边,要作修改的地址,在被调用函数中对数组值的修改都是可见的,BubbleSort,函数:,使用,a0,保存形参,list,的值,,a1,保存形参,n,的值,使用,s1,、,s2,和,s3,保存局部变量,i,,,j,和,temp,的值,运行时栈,BubbleSort,01 BubbleSort:addisp,sp,-12,#,分配栈帧,02,sws1,0(sp),#,寄存器,s1,的保存,03,sws2,4(sp),#,寄存器,s2,的保存,04,sws3,8(sp),#,寄存器,s3,的保存,05,#,06,lis1,1,#i=1,07 OutLoop:addit0,a1,-1,#n-1,08bgts1,t0,exit_1,#i=n-1,09lis2,1,#j=1,0A InLoop:subt0,a1,s1,#n-i,0Bbgts2,t0,exit_2,#j listj),temp=listj-1;,listj-1=listj;,listj=temp;,10sllit2,s2,2,#j*4,11addt2,a0,t2,#&listj,12,lwt3,0(t2),#listj,13bget3,t1,exit_3,#if(listj-1 listj),14mvs3,t1,#temp=listj-1;,15,swt3,0(t0),#listj-1=listj;,16,sws3,0(t2),#listj=temp;,17 exit_3:addis2,s2,1,#j+,18jInLoop,19 exit_2:addis1,s1,1,#i+,1AjOutLoop,1B exit_1:lws3,8(sp),#,恢复寄存器,1Clws2,4(sp),1Dlws1,0(sp),1Eaddisp,sp,12,#,弹出栈帧,1Fret,if(listj-1 listj),temp=listj-1;,listj-1=listj;,listj=temp;,字符串比较,StrCmp,函数,按照字典顺序比较两个字符串,如果第一个字符串排在第二个之前,返回,-1,,如果排在第二个之后,返回,1,,如果二者相同,则返回,0,StrCmp,函数,int StrCmp(char*firstStr,char*secondStr),int i=0;,int res;,while(!(res=firstStri-secondStri)&secondStri),i+;,/*,如果二字符相同且第二个字符串未到末尾,继续比较,*/,if(res 0),res=1;,return res;,StrCmp,函数,使用,a0,保存形参,firstStr,的值,,a1,保存形参,secondStr,的值,使用,s1,和,s2,保存局部变量,i,和,res,的值,使用,a0,保存返回值,StrCmp,01 StrCmp:addisp,sp,-8,#,分配栈帧,02sws1,0(sp),#,寄存器,s1,的保存,03sws2,4(sp),#,寄存器,s2,的保存,04,#,05lis1,0,#i=0,06 loop:addt0,a0,s1,#&,firstStri,07,lbt0,0(t0),#,firstStri,08addt1,a1,s1,#&secondStri,09,lbt1,0(t1),#secondStri,0Asubs2,t0,t1,#res=firstStri-secondStri,0Bbnezs2,exit_1,#!(res=firstStri-secondStri)?,0Cbeqzt1,exit_1,#secondStri?,0Daddis1,s1,1,#i+;,0Ejloop,while(!(res=firstStri-secondStri)&secondStri),0F exit_1:beqzs2,end,10bltzs2,exit_2,#res 0?,11lis2,1,#res=1;,12jend,13 exit_2:lis2,-1,#res=-1;,14 end:,mva0,s2,#return res;,15lws2,4(sp),#,恢复,s2,寄存器,16lws1,0(sp),#,恢复,s1,寄存器,17addisp,sp,8,#,弹出栈帧,18ret,return res;,printf,函数的参数传递,printf,函数的第一个参数是一个格式用,字符串,在,printf,函数调用时,在格式用字符串中的每一个转换说明和出现在格式用字符串后面的每个参数之间存在着一个,一一对应,的关系,例如:,printf(valueA=,%d,and valueB=,%d,n,valueA,valueB,);,printf,函数,使用,a0,保存第一个形参的值,格式用,字符串的首地址,格式用字符串被存储于,静态数据区,使用,a1,和,a2,保存来自实参,valueA,和,valueB,的值,调用,printf,01.data,02,String:.string,valueA=%d and valueB=%dn,03,#,04.text,05,#,省略其他代码,06mva2,t1,#,传递参数,a2-valueB,07mva1,t0,#,传递参数,a1-valueA,08laa0,String,#,传递参数,a0-String,09,callprintf,传递参数,绝大多数编译器的参数传递方向都是“,自右向左,”,printf,0A,#,以下为,printf,相关代码,0B stdout:.byte,0,0,.,#,标准输出流,共,size,个字节,0C,#,0D printf:,0E,#,省略如下功能代码:,0F,#,根据,a0,所指的格式用字符串中的转换说明,将,a1ax,中的值转换为字符序列,10,#,存储到标准输出流,stdout,中,11,#,遇,n,或输出流已满,自陷进入操作系统处理例程,12laa0,4,#puts,13laa1,stdout,14,ecall,15,#,省略其他代码,16ret,可变参数列表,传给,printf,函数的参数的个数是不确定的,参数个数取决于被打印的项目的个数,寄存器和内存的分配,如果传给,printf,函数的参数个数多于,8,个,先使用,a0a7,存储前,8,个参数值,剩下的参数则被分配到栈帧中,可变参数列表,如果,printf,函数的转换说明与参数不对应,printf(The value of nothing is,%d,n);,在调用,printf,函数时,将格式用字符串首地址传给,a0,寄存器,进入,printf,函数后,假定正确的参数个数已被传递,a0,寄存器:格式用字符串的首地址,a1,:对应于说明,%d,的参数,无论此时,a1,中的值是什么,都会作为参数被转换,scanf,函数的参数传递,scanf,函数也具有可变参数列表,第一个参数也是一个格式用字符串,从第二个参数开始,传递的实参都是变量地址,例如:,scanf(%d,&input,);,从输入流的下一个非空白字符开始,找到一个十进制数的,ASCII,序列,将其转化为整数,并存储在对应的变量,input,中,scanf,函数,使用,a0,保存第一个形参的值,格式用字符串的首地址,使用,a1,保存来自实参“,&input”,的值,调用,scanf,01.data,02String:.string%d,03,#,04.text,05,#,省略其他代码,06addit0,sp,0,#&input,,假设,input,位于栈顶,07mva1,t0,#,传递参数,a1-&input,08laa0,String,#,传递参数,a0-String,09,callscanf,0Alwt0,0(sp),#input,,已得到输入的整数,scanf,0B,#,以下为,scanf,相关代码,0C stdin:.byte,0,0,.,#,标准输入流,共,size,个字节,0D,#,0E scanf:,0F,#,省略如下功能代码:,10,#,根据,a0,所指的格式用字符串中的转换说明,从,stdin,中找,ASCII,序列,11,#,如果输入流中无字符,则自陷,12,#,如果有字符,根据格式说明寻找相应的,ASCII,序列,进行转换,例如,13,#,如果格式说明为“,%d,”,抛弃掉开头的空白字符,,14,#,读入一串以“非数字”结束的十进制数,ASCII,序列,,15,#,如果存在这样的,ASCII,序列,就转化为一个二进制整数,并存储,16,swt0,0(a1),#,存储到,a1,所指的地址中,17,#,省略其他代码,18ret,省略“,&”,运算符,scanf(%d,input,);,假如,t1,中得到的是,input,的值,将,input,的值传给,a1,产生,运行时错误,错误在执行程序的过程中被发现,程序正试图去修改一个它不能访问的存储单元,例如,