Goto到另一个函数内部
Goto到另一个函数内部的用法,在现存的高级语言中基本上已经绝迹了。但并非异想天开。也没有特别复杂。现在来探讨一下。
要允许Goto到另一个函数内部,首先要有语法的支持。假设这样写吧:
func daily(n)
{
while(n>0) {
n--;
switch(iday) {
case 0:
case_sunday: print "Sunday"; iday=1; break;
case 1:
case_Monday: print "Monday"; iday=2; break;
case 2:
case_tuesday: print "Tuesday"; iday=3; break;
case 3:
case_wednesday: print "Wednesday"; iday=4; break;
case 4:
case_thursday: print "Thursday"; iday=5; break;
case 5:
case_friday: print "Friday"; iday=6; break;
case 6:
case_saturday: print "Saturday"; iday=0; break;
}
}
}
goto daily(31).case_friday;
这个goto的意思是调用函数daily(31),但是从标号case_friday处开始执行。打印Friday开始31天的星期历。这里函数看作了标号的结构体。这样函数就不再是唯一入口的代码块了。
在实现上也不是特别困难。原来函数调用的地方,只要稍作修改:
struct exprval e_fcall(int fi, struct node *paras, int *exception)
{
struct funxat *f;
struct node *p;
struct exprval e;
int i;
struct exprval ret;
struct exprval *argtab = NULL;
f = &userfunc[fi];
p = paras;
i=0;
while(p) {
p = p->left;
++i;
}
if (i != f->paras) {
printf("function %s(...) need %d paras, but given %d\n",
f->name, f->paras, i);
*exception =1; goto exception_out;
}
if(f->paras>0) {
argtab = (VALUE_TYPE *)Malloc(sizeof(VALUE_TYPE)*f->paras);
}
p = paras;
for(i=f->paras-1; i>=0; --i) {
e = e_eval(p->right, exception); EXCEPTION_CHK;
argtab[i]= e;
p= p->left;
}
if (f->loop == f->warning) {
printf("waring: func %s(...) nest called in %d levels\n",
f->name, f->loop);
f->warning = terminate_loop -(terminate_loop -f->warning)/4;
}
if (f->loop >terminate_loop) {
printf("exception: func %s(", f->name);
for(i=0; i<f->paras; i++) {
if(i>0) printf(",");
e = argtab[i];
if (e.type==0) {
printf("~%d", e.u.value);
}
else {
printf("~%lf", e.u.d_value);
}
}
printf(") is terminated!;\n");
*exception =1;
goto exception_out;
}
f->loop++;
alloc_context(f);
for(i=0; i<f->paras; i++) {
stk->e[top].bp[i] =argtab[i];
}
execute_e_ls(f->syntree, 0, exception); //.. ..............
ret = stk->e[top].ret;
free_context();
f->loop--;
if (f->loop==0) {
f->warning= terminate_loop - (terminate_loop/4);
}
exception_out:
if (argtab) free(argtab);
if (*exception==1) {
}
return ret;
}
改为:
struct exprval e_fgoto(int fi, struct node *paras, char *sgoto, int *exception)
{
...
i = labelfind(f, sgoto, strlen(sgoto));
if(i<0) {
*exception =1;
goto exception_out;
}
execute_e_ls(f->syntree, f->labeltab[i], exception);
...
}
函数增加goto的目标label参数,原来的execute_e_ls(f->syntree, 0, exception); 变为带goto标记的execute_e_ls(f->syntree, f->labeltab[i], exception);
这样做可能毫无意义,也可能…。偶尔,有一天你会想把几个不同实现的排序代码封装到一个sort()函数中,又允许使用时调用各自的功能:
func sort(array, first, last)
{
bubble_sort:
...
return;
quick_sort:
...
if(...) goto sort(array, first, middle-1).quick_sort;
if(...) goto sort(array, middle+1, last).quick_sort;
return;
}
可以用goto sort(array, first, last).quick_sort;来调用快速排序。当然,这局部是个递归,它也是用同样的句法来调用自己。
如果增加一个函数参数来选择怎么样?
func sort(array, first, last,select)
{
if(select==1) goto bubble_sort;
if(select==2) goto quick_sort;
bubble_sort:
...
return;
quick_sort:
...
if(...) sort(array, first, middle-1, select);
if(...) sort(array, middle+1, last, select);
return;
}
这样当然可以…。不过多了一个参数,以及一些选择语句。开销也可以忍受。不过在递归过程中这样写,让人不快。
最后,如果函数有返回值呢?只要允许到变量的一个赋值语句就可以了:
goto n = fib(i).lable1;
原文地址:https://blog.csdn.net/aaasssdddd96/article/details/136392352
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!