C语言调用一个函数无法跳出,死循环

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言调用一个函数无法跳出,死循环相关的知识,希望对你有一定的参考价值。

这是主函数:
main()

// Init_lcd1602();
Init_timer();

// Wlcd_string(0x80,word1);
// Wlcd_string(0xc0,word2);
while(1)

// Wlcd_string(0xc0,word2);
keyscan(); 问题是调用keyscan()函数后还会继续跳回这一句,循环调用这个函数,不往下走,这是怎么回事?请大侠们给指导一下。
Wlcd_cmd(0xc0);
Wlcd_data(2 + '0');



这是被调用的子函数,单独源文件
void keyscan (void)

P2 = 0xf0;
if((P2&0xf0) != 0xf0)

switch (P2)

case 0xe0:
row = 1;
break;
case 0xd0:
row = 2;
break;
case 0xb0:
row = 3;
break;
case 0x70:
row = 4;
break;
default:
break;


for (i=1000;i>0;i--);

P2 = 0x0f;
if((P2&0x0f) != 0x0f)

switch (P2)

case 0x07:
tier = 1;
break;
case 0x0b:
tier = 2;
break;
case 0x0d:
tier = 3;
break;
case 0x0e:
tier = 4;
break;
default:
break;



Key_value = 4*(tier-1)+row;

可能是我没说太清楚,现在的问题不是while(1)死循环的问题,我就是要这个死循环。
问题是main函数里调用keyscan()函数后,不继续往下走,而是重新调用keyscan(),这个死循环不是我想要的,也想知道问题在哪?

不过我自己已经解决了。就是把Key_value = 4*(tier-1)+row;这句提到它上面那个大括号以内。原因大家可以探讨一下,我暂时还没想通。

应该是已经走了。
但是你Keyscan后就调用另外两个函数。而两个函数也没有个执行的显示,所以看上去就象是一直在执行keyscan函数一样。
而且你的while(1)这个执行条件,一直就是真。所以,你这个程序,首先是无法跳出循环。
第二,循环肯定是已经执行了另外两个方法,但是因为你的两个函数没有输出提示,所以你误以为没有执行。
建立你在两个函数里用两个输出语句,你就可以看到,你的这两个函数实际已经执行了。追问

不是这样的,main函数里后两个函数会输出一个数字2,这个是为了调试用,我设置断点测试过了,确实是死在keyscan这句调用语句了。

追答

那可以跟踪一下Keyscan函数,看看执行到什么地方.或者你还是在个函数执行的每一句后面都输出点东西看看:
main()

// Init_lcd1602();
Init_timer();

// Wlcd_string(0x80,word1);
// Wlcd_string(0xc0,word2);
while(1)

out("准备执行keyscan");
keyscan(); 问题是调用keyscan()函数后还会继续跳回这一句,循环调用这个函数,不往下走,这是怎么回事?请大侠们给指导一下。
out("执行keyscan完成");
out("准备执行Wlcd_cmd");
Wlcd_cmd(0xc0);
out("执行WlCd_cmd完成");
Wlcd_data(2 + '0');

参考技术A while(1)

你这个条件永远为真,所以是这个循环死循环了,你可以再里面设置一个标记flag 当flag为假的时候跳出while循环追问

可能我没说太清楚,现在是死循环在keyscan()这个调用函数语句上。while(1)没问题。

参考技术B while(1)

// Wlcd_string(0xc0,word2);
keyscan();
Wlcd_cmd(0xc0);
Wlcd_data(2 + '0');

不是调用函数的问题。。。。while(1)条件永远为真 循环内部又没有跳出点 所以死循环了
参考技术C 两处 switch (P2) 这个写法不对, 不能正确的扫描到按键情况 换成下面的:
switch (P2&0x0f)
switch (P2&0xf0)
其它的你得自己检查函数 Wlcd_data(); 看它内部有没有把你的相关信息输出
参考技术D 真不知道你写那个keysan()函数干嘛用的,也没看到你在哪里定义了变量tier,
P2 = 0xf0;
if((P2&0xf0) != 0xf0)

switch (P2)

case 0xe0:
row = 1;
break;
case 0xd0:
row = 2;
break;
case 0xb0:
row = 3;
break;
case 0x70:
row = 4;
break;
default:
break;



你觉得这些语句有用吗?
for (i=1000;i>0;i--);

这个语句纯粹是浪费时间。

C语言函数参数压栈顺序为何是从右到左?(从左向右的话,碰到printf的会陷入死循环)

上学期学习了汇编语言,并在操作系统实验中使用了汇编+C语言混合编程,中间也了解了一些C语言与汇编语言的对应关系。
由于汇编语言是底层的编程语言,各种函数参数都要直接控制栈进行存取,在混合编程中,要用汇编来调用C函数,当然就要知道参数的压栈情况了。
当知道C函数的参数压栈顺序是从右到左时,我觉得很奇怪,因为大多数情况下,人们的习惯是从左到右的,难不成设计者学咱们中国古代写字从右到左的习惯不成?
当时只是记下了这个规则而已,并没有去探究这其中的缘由,后来在实验中自己用汇编实现了printf和scanf函数的基本功能,尝到了压栈从右到左的好处,但是仍然没有多想。
直到前阵子看斯坦福大学公开课的时候,老师解释了一番才恍然大悟!
那么,这是为什么呢?
要回答这个问题,就不得不谈一谈printf()函数,printf函数的原型是:printf(const char* format,…)
没错,它是一个不定参函数,那么我们在实际使用中是怎么样知道它的参数个数呢?这就要靠format了,编译器通过format中的%占位符的个数来确定参数的个数。
现在我们假设参数的压栈顺序是从左到右的,这时,函数调用的时候,format最先进栈,之后是各个参数进栈,最后pc进栈,此时,由于format先进栈了,上面压着未知个数的参数,想要知道参数的个数,必须找到format,而要找到format,必须要知道参数的个数,这样就陷入了一个无法求解的死循环了!!
而如果把参数从右到左压栈,情况又是怎么样的?函数调用时,先把若干个参数都压入栈中,再压format,最后压pc,这样一来,栈顶指针加2便找到了format,通过format中的%占位符,取得后面参数的个数,从而正确取得所有参数。
所以,如果不存在…这种不定参的函数,则参数的压栈顺序无论是从左到右还是从右到左都是没关系的。

http://m.blog.csdn.net/article/details?id=47381597

以上是关于C语言调用一个函数无法跳出,死循环的主要内容,如果未能解决你的问题,请参考以下文章

函数调用形成死循环怎么办

C语言中啥叫死循环?怎么避免?

linux 下调用recv函数,死循环在recv函数里面,啥原因?

C语言函数参数压栈顺序为何是从右到左?(从左向右的话,碰到printf的会陷入死循环)

C语言中死循环怎么解决?

循环语句中while(1)中的1是啥意思