浅析goto语句以及longjmp函数
在各种计算机语言中,程序结构主要有顺序结构,分支结构,循环结构3大主体。
顺序结构:程序按照自然代码顺序进行执行。
主要的分支语句有:if,if-else,if-else if -else, switch...
主要的循环语句有:while,do-while, for...在循环中,又可以根据需求,跳过某一次的循环语句(break-跳出本层循环,continue-绕过后边的语句进入下一次循环)。
入题
那么有些时候,我们就是要任性的或者说真正的需求跳到某个特定的代码块运行我们的逻辑,那么break或者continue就不能满足我们的要求了(break,continue都是跳过一层循环的)。这就是goto语句出场的时机了。goto语句:
goto语句也称为无条件转移语句,其一般格式如下:
goto 语句标号;
其中语句标号是按标识符规定书写的符号, 放在某一语句行的前面,标号后加冒号(:)。语句标号起标识语句的作用,与goto 语句配合使用。
示例:
<span style="font-size:18px;"> int count = 0; //做100次无用功
for(int i = 0;i<100;++i)
{
<span style="background-color: rgb(255, 204, 102);">Start:</span>
printf("one\t");
for(int j = 0;j<100;++j)
{
printf("tow\t");
for(int k = 0;k<100;++k)
{
count++;
if(count == 100)
exit(1); //只有如此才能真正退出了
//return //return 退出本程序,也是一种方法
if(k == 10)
<span style="background-color: rgb(255, 204, 0);">goto Start;</span>
printf("three-%d\t",k);
}
}
}
}</span>
是否感觉lz举得这个例子让你并没有体验到goto的伟大之处,这个不重要。因为现在的程序,没有多少人会提倡goto的使用。你只需要了解,有这么个伟大的语句,他可以给你任性的跑路。
那么下边就说说关于longjmp了:
- void longjmp (jmp_buf env, int val);
- jmp_buf //Type to hold information to restore calling environment
- 注:这两个东东弥补了C语言有限的转移能力
- setjmp(jmpbuf j )必须首先被调用,世博那个变量j 记录现在的位置 函数返回0
- longjmp()接着被调用,回到 j 所记录的位置,返回值为第二个参数(可以加以利用)
- 当使用longjmp()时,j 内容被自动销毁
- setjmp保存的是程序计数器和当前栈顶指针,被称为“展开堆栈” 只能回到曾经去过的地方
- goto只能在本函数内装逼,,longjmp甚至可以跳跃文件,,,(走过路过,不会错过)
/* longjmp example */
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
main()
{
jmp_buf env;
int val;
val=setjmp(env);
printf ("val is %d\n",val);
if (!val) longjmp(env, 1);
return 0;
}
Output:
val is 0
val is 1
该函数过程,运行从test回到TTT或者main(这些都是调用它的函数)
<span style="font-size:18px;">#include <stdio.h>
#include <setjmp.h>
jmp_buf buf;
void test()
{ printf("in test(test)\n");
int a = 0;
cin>> a;
if (a==1)
longjmp(buf,1);
else if(a==2)
longjmp(buf,2);
printf("this is never see(test)\n");
}
void TTTTT()
{
Begin:
int a = setjmp(buf);
if(a==1)
{
printf("1111Back in (TTTTT)\n");
goto Begin;
}
else if(a==2)
{
printf("2222Back in (TTTTTT)\n");
goto Begin;
}
else
{
printf("first here(TTTTTTTT)\n");
test();
}
}
int main()
{
Begin:
int a = setjmp(buf);
if(a==1)
{
printf("1111Back in (Main)\n");
goto Begin;
}
else if(a==2)
{
printf("2222Back in (Main)\n");
TTTTT();
goto Begin;
}
else
{
printf("first here(Main)\n");
test();
}
}</span>
该函数过程,运行从test回到TTT或者main(这些都是调用它的函数)
该函数过程,运行从test回到TTT或者main(这些都是调用它的函数)