铺垫: 变量名实质上是一段连续存储空间的别名,是一个标号 程序中通过变量来申请并命名内存空间 通过变量的名字可以使用存储空间 (能不能再名字的基础上在起个名字?) 概念: 1)可以看做一个已定义变量的别名 引用是c的语法范畴,不能再用c语言的思想去思考问题(间接修改) 属于c编译器对c的扩展 引用做函数参数 普通引用在声明时必须用其他的变量进行初始化 引用作为函数参数声明时不进行初始化includeiostreamusingnamespacestd;引用基本用法voidmain(){inta10;intba;b100;printf(b:d,b);printf(a:d,a);couthello。。。。endl;system(pause);return;}voidmain11(){inta10;intba;intc;普通引用必须要初始化system(pause);}voidmyswap01(inta,intb){intc0;ca;ab;bc;}voidmyswap02(inta,intb){intc0;ca;ab;bc;}voidmyswap03(inta,intb){intc0;ca;ab;bc;}voidmain(){intx,y;x10;y20;myswap01(x,y);printf(x:d,y:d,x,y);myswap02(x,y);printf(x:d,y:d,x,y);myswap03(x,y);printf(x:d,y:d,x,y);system(pause);}复杂数据类型的引用structTeacher{charname〔64〕;intage;};voidprintfT(TeacherpT){coutpTageendl;}pT是t1的别名,相当于修改了t1voidprintfT2(TeacherpT){coutpT。ageendl;}pT和t1是两个不同的变量voidprintfT3(TeacherpT){coutpT。ageendl;pT。age45;只会修改pT变量,不会修改t1变量}voidmain(){Teachert1;t1。age35;printfT(t1);printfT2(t1);pT是t1的别名printfT3(t1);pT是形参,t1拷贝了一份数据,给pTprintf(t1。age:d,t1。age);couthello。。。。endl;system(pause);return;} 引用的意义 引用作为其他指针变量的别名而存在,因此在一些场合可以替代指针 引用相对于指针来说具有更好的可读性和实用性 引用的本质 c编译器背后做了什么工作 单独定义的时候必须初始化很像常量 1)引用在c内部实现是一个常指针 2)c编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占的空间与指针相同 3)从使用的角度,引用会让人误会其只是一个别名,没有自己的储存空间,这是c为了实用性做出的细节隐藏。 结论:当我们使用引用的语法时,我们不用去关心编译器引用是怎么做了 当我们分析奇怪的语法现象时,才去考虑编译器是怎么做的includeiostreamusingnamespacestd;voidmain01(){constintc110;inta10;intba;像常量printf(a:d,a);printf(b:d,b);ab就是同一块内存空间的门牌号依附于这个内存空间couthello。。endl;system(pause);return;}普通引用有自己的空间吗?有,和指针所占的一样structTeacher{charname〔64〕;64intage;4inta;4intb;4};引用的本质一个常量指针voidmain(){printf(sizeof(Teacher):d,sizeof(Teacher);system(pause);}voidmodifyA(inta1){a1100;}voidmodifyA2(intconsta1){a110;实参的地址,去间接修改实参的值}voidmain(){inta10;modifyA(a);指向这个函数调用的时候,我们程序员不需要取a的地址printf(a:d,a);modifyA2(a);如果是指针需要我们手工去取实参地址printf(sizeof(Teacher):d,sizeof(Teacher));system(pause);}间接赋值间接赋值成立的三个条件1定义2个变量2建立关系实参取地址传给形参3形参间接修改实参的值voidmodifyA3(intp){p190;3}voidmain(){inta10;intpNULL;1pa;p100;{p200;}modifyA3(a);2}引用是间接赋值哪几个条件的组合?2编译器做了123后2个条件写在一起了只不过2编译器做了 函数返回值是引用(引用当左值) c引用使用时的难点: 当函数返回值为引用时, 若返回栈变量,不能成为其他引用的初始值,不能作为左值使用 若返回静态变量或全局变量可以成为其他引用的初始值。 即可作为右值使用,也可作为左值使用includeiostreamusingnamespacestd;intgetAA1(){inta;a10;returna;}返回a的本身intgetAA2(){inta;a10;returna;}intgetAA3(){inta;a10;returna;}voidmain01(){inta10;inta20;a1getAA1();a2getAA2();inta3getAA2();printf(a1:d,a1);printf(a2:d,a2);printf(a3:d,a3);couthello。。endl;system(pause);return;}返回静态全局intj(){staticinta10;a;returna;}intj(){staticinta10;a;returna;}voidmain(){inta110;inta220;a1j1();a2j2();inta3j2();printf(a1:d,a1);printf(a2:d,a2);printf(a3:d,a3);couthello。。endl;system(pause);return;}函数当左值返回变量的值intg(){staticinta10;a;returna;}返回变量本身intg(){staticinta10;a;returna;}voidmain(){g1()100;执行这个,函数返回值就是11。不成立errg2()100;把上面的函数改成了100,所以这个就成立system(pause);} 指针的引用includeiostreamusingnamespacestd;structTeacher{charname〔64〕;intage;};intgetTeacher(Teacherp){TeachertmpNULL;if(pNULL){return1;}tmp(Teacher)malloc(sizeof(Teacher));if(tmpNULL){return2;}page33;ptmp;}指针的引用做函数参数intgetTeacher2(Teachermyp){给myp赋值相当于给主函数中的pT1赋值myp(Teacher)malloc(sizeof(Teacher));if(mypNULL){return1;}page36;}voidFreeTeacher(TeacherpT1){if(pT1NULL){return;}free(pT1);}voidmain(){TeacherpT1NULL;getTeacher(pT1);二级指针coutage:pT1ageendl;FreeTeacher(pT1);getTeacher2(pT1);引用coutage:pT1ageendl;FreeTeacher(pT1);couthello。。endl;system(pause);return;} c中的const常量 可能分配内存空间,也可能不分配 当const常量为全局,并且需要在其他文件中使用,会分配空间 在使用操作符,取const常量的地址,会分配 当const修饰引用,会分配includeiostreamusingnamespacestd;voidmain(){intx20;constintyx;常引用让变量拥有只读属性不同通过y去修改x了常引用初始化分为2种情况1)用变量初始化常引用{intx130;constinty1x1;}2)用字面量初始化常引用{constinta40;intm41;普通引用引用一个字面量字面量有没有内存地址?没有}couthello。。endl;system(pause);return;} 结论: constinteconstintconste 普通引用intconste 当使用常量对const引用进行初始化时,编译器会为常量值分配空间,并用引用名作为这段空间的别名 使用字面量对const引用初始化后,将生成一个只读变量