程序中的临时变量都是存放在进程的堆栈中的,那么要实现队列,只需要在一次函数调用中不释放函数中的局部变量,然后让一个指针始终指向队列头,另一个指针始终指向队列的第二个成员就可以了。这时,就需要被调用的函数不能退出,那么它的所有局部变量就不会被释放。
为了做一个例子,我们让一个函数递归调用它自身,知道满足一定条件以后,才能把堆栈中的函数取出来继续执行。当然,在现实中,更多的情况是某些进程因为资源竞争而等不到资源,只好被迫睡眠,这就可以使用堆栈的方式来创建一个等待队列。
实例程序的过程:有一全局变量的指针,始终指向队列的头元素,把它叫做head好了;在函数中,有一局部变量lnode和一个局部变量的指针tmp。函数的功能就是给lnode赋值,并且判断条件是否成立:如果不成立,则递归调用该函数;如果成立,就把函数出栈,打印队列头的值,并把队列头向后移动一个位置。
#include <stdio.h>
struct node {
int id;
};
static struct node *head; //全局头指针
/* 判断条件:
* 如果某一个flags[i]为1,这递归调用,知道所有的flags[i]都为0
*/
static int flags[5] = { 1, 1, 1, 1, 1 };
static int done = 0; //函数从栈中弹出时,需要判断是否所有的flags[i]都已经为0
void recursion()
{
struct node lnode; //局部变量
struct node *tmp; //局部变量指针,指向队列的第二个元素
int i;
for (i=0; i<5; i++) {
if (flags[i]) { //如果flags[i]不为0
flags[i] = 0;
lnode.id = i + 1; //给局部变量赋值
tmp = head; //让tmp指向队列的第二个元素
head = &lnode; //让head指向队列的头
recursion();
}
/* 以下代码只有从栈中弹出的函数会执行 */
if (done) {
head = tmp;
break;
}
}
/* 以下代码会在最后一次调用recursion()(也就是在所有已入栈的函数出栈前)时第一次被执行
* 设置done标志,让从栈中弹出的函数知道flags[i]已经都为0了,需要把head指针向后移一位
*/
done = 1;
if (head) //如果head不为空,为空说明栈中的数据已经取完了
printf("%d\n", head->id);
}
int main()
{
recursion();
return 0;
}
最后执行结果会打印出 5, 4, 3, 2, 1。如果代码我解释得不太清除,可以结合gdb调一下,很容易看清楚这个过程的。