return是啥
return其英文含义就是返回,用在函数中,退出当前函数。这个想必都知道,分两种情况:
void?func(void)
{
???/*功能代码*/
???...
???return;
}
对于不带返回值函数返回,其语法为 return;对于void函数,通常不显式加return语句,程序会自动返回到其调用者现场。
所以上述函数如下改写一下,效果是一样的:
void?func(void)
{
???/*功能代码*/
???...
}
int?add(int?a,?int?b)
{
????int?result?=?a+b;
????return?result;
}
对于带返回值函数返回,其语法为 return <value>;返回值可以是一些几种情况:
-
一个常数 -
一个变量 -
计算式,例如(a + b)* c -
调用另一个返回值的函数
注意:返回值的类型须与函数返回值类型一致,如不一致,编译器会自动做类型转换,这里容易出现类型转换的错误
上代码:
/*Case?1,返回常量*/
/*返回常量,-1表示参数非法,0表示成功*/
int?swap(int?*a,?int?*b)
{
????int?temp;
????if(a==NULL?||?b==NULL)
????????return?-1;
????else
????{
????????temp?=?*a;
????????*a?=?*b;
????????*b?=?temp;
????????return?0;
????}
}
/*Case 2:返回一个变量*/
int?add(int?a,?int?b)
{
????int?result?=?a+b;
????return?result;
}
/* Case 3:返回一个表达式,add函数改写一下*/
int?add(int?a,?int?b)
{
????return?(a+b);
}
/*?Case?4:返回一个函数调用?*/
/*STM32编程:是时候深入理解栈文章中提到的递归计算阶乘*/
float?factorial(uint32_t?n)
{
????uint32_t?sp?=?__get_MSP();????
????/*记录栈指针的变化情况*/
????spSatte[spIndex++]?=?sp;
????if(n==0?||?n==1)
????????return?1;
????else
????????return?(float)n*factorial(n-1);
}
return 咋工作的?
首先需要了解函数调用是如何工作的。当调用一个函数时,会发生两件事:
-
当前函数的执行暂停。 -
调用的函数执行。
这就是所谓的的控制权转移。当调用一个函数时,程序的控制从调用函数转移到被调用函数。return语句将控制权返回到前一个调用它的函数。该函数将从暂停的地方继续执行。
在调用处,如果查看汇编代码,单片机或处理器会将当前CPU的PC指针、临时变量、相关寄存器压栈,调用函数返回时,会将栈的内容弹出到相应的寄存器或者临时变量,以恢复现场。关于栈的解释可以参见号内文章:<<STM32编程:是时候深入理解栈>>
void 函数真不需要加return吗?
事实上不然,这就是本文希望引起注意的一些要点,在哪些场景下需要显式的对void函数添加return语句呢?
void?swap(int?*a,?int?*b)
{
????int?temp;
????/*不可操作空指针*/
????if(a==NULL?||?b==NULL)
????????return?;
????else
????{
????????temp?=?*a;
????????*a?=?*b;
????????*b?=?temp;
????}
}
enum?E_DAY{?
????E_MON=0,?
????E_TUS,
????E_WNd,?
????E_THR,
????E_FRD,?
????E_SAT,?
????E_SUN?
};
void?set_day(E_DAY?day,E_DAY?*pDay)
{?
????/*?这里就需要判别day参数是否非法越界?*/
????if(day>E_SUN?||?day<E_MON?||?pDay?==NULL)
?????return;
?????
????*pDay?=?day;
}
void?func(void)
{
????FILE?*pFile=fopen("./test.csv","wt+");
????/*这里就检测到文件无法打开的异常,则需要马上退出*/
????if(pFile==NULL)
????{
????????printf("file?opened?failed");
????????return?;
????}
????.....
????fclose(pFile);
}
总结一下
因为容易忽略,其实也是初学者可能不太注意的一些地方,所以在此总结一下:
-
return的具体做了什么,其内在工作原理需要栈的支持 -
不带返回值的函数,可不加return语句 -
带返回值的函数,注意返回值的类型与函数返回值类型一致 -
void函数,在一些特定的场合加上return语句,可增加程序的健壮性: -
-
传入指针为空指针 -
传入参数非法或者越界 -
检测到异常时需立即退出当前程序的执行流 -
其实非void函数,也强烈建议这么处理。
|