搜索
bottom↓
回复: 23

c语言中跳转不正常的问题。【涉及protothreads内核源代码分析】

[复制链接]

出0入25汤圆

发表于 2022-7-3 07:51:09 | 显示全部楼层 |阅读模式

各位大神大家好:

      小弟最近在看protothreads源代码,并且在学习过程中遇到了一个非常诡异的问题,源代码运行如下:

  1. #include <stdio.h>


  2. int aa()
  3. {
  4.         static int i;
  5.        
  6.         static int sta =0;
  7.        
  8.         switch(sta)
  9.         {
  10.                 case 0 :
  11.                         for(i=0;i<10;i++)
  12.                         {
  13.                                 sta = 1 ;
  14.                                 return i;                
  15.                 case 1:  ;
  16.                                 //if(i== 5)
  17.                                         //return 5;
  18.                         }       
  19.         }
  20.        
  21.         //return 6;
  22.        
  23. }


  24. int main()
  25. {
  26.         int kk;
  27.        
  28.    /* 我的第一个 C 程序 */
  29.    printf("Hello, World! \n");

  30.         for(kk=0;kk<20;kk++)
  31.         {
  32.                 printf("%d ",aa());
  33.         }
  34.        
  35.    return 0;
  36. }
复制代码



代码运行的效果:





问题:
  当把 //return 6;  注释掉, i竟然能正常返回,并且大于10 ?  这是为什么?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。

出0入16汤圆

发表于 2022-7-3 08:16:15 | 显示全部楼层
case放在for循环里,第一次学习。。。case都是不完整的break跳出,确认不是乱写的吗,逻辑混乱,看到手下这么写一顿批

出0入25汤圆

 楼主| 发表于 2022-7-3 08:29:53 | 显示全部楼层
初音之恋 发表于 2022-7-3 08:16
case放在for循环里,第一次学习。。。case都是不完整的break跳出,确认不是乱写的吗,逻辑混乱,看到手下这 ...
(引用自2楼)


这是国外大神写的。 一般人是写不出来的。

已经是无招胜有招了

出100入312汤圆

发表于 2022-7-3 08:48:20 来自手机 | 显示全部楼层
实现了分时调度,挺好用

出0入25汤圆

 楼主| 发表于 2022-7-3 08:58:00 | 显示全部楼层
akey3000 发表于 2022-7-3 08:48
实现了分时调度,挺好用
(引用自4楼)

是的。只是还有点问题。 见1楼的问题

出0入31汤圆

发表于 2022-7-3 09:46:17 | 显示全部楼层
我以为至少会有告警,可能太技巧了,能工巧匠!

出0入0汤圆

发表于 2022-7-3 12:16:17 | 显示全部楼层
case的入口类似goto语句的标号,case的判断是在switch中,所以case后面不允许变量的。
这些技巧就好像goto语句的用法,例如goto进一个for循环里面会发生啥事情?
有可能不同编译器出来不同运行效果。

出0入0汤圆

发表于 2022-7-3 12:53:10 | 显示全部楼层
C语言的case实质上只是一个标签,除了第1次函数调用跳到case 0处,以后每次函数调用都是跳到case 1处执行

出0入25汤圆

 楼主| 发表于 2022-7-3 13:36:59 | 显示全部楼层
modbus 发表于 2022-7-3 12:53
C语言的case实质上只是一个标签,除了第1次函数调用跳到case 0处,以后每次函数调用都是跳到case 1处执行 ...
(引用自8楼)

为什么能打出 11 12 13 14 …… ?

出0入663汤圆

发表于 2022-7-3 13:55:07 | 显示全部楼层
看汇编不就知道怎么回事了么。

出0入0汤圆

发表于 2022-7-3 18:14:37 | 显示全部楼层
本帖最后由 modbus 于 2022-7-4 14:10 编辑
rei1984 发表于 2022-7-3 13:36
为什么能打出 11 12 13 14 …… ?
(引用自9楼)


case 1处就是for循环的},一般就是执行i++并判断i<10并跳转(还要看编译器)

出130入20汤圆

发表于 2022-7-3 22:29:53 | 显示全部楼层
感觉这种写法飘逸是飘逸,但是很吃编译器,不同的编译器有的可能警告,有的可能编译出的结果不是你想要的

出0入663汤圆

发表于 2022-7-4 08:32:59 | 显示全部楼层
这个程序-O0和-O2出来的运行结果不一样,-O2后面只会一直返回9。

出0入362汤圆

发表于 2022-7-4 10:19:52 | 显示全部楼层
既然是gcc, 要不改用goto label的方式? 记得pt是两种都支持的

能用goto label的话就不用魔改switch了, 不然在自己的子协程里再想用switch就可能要出问题了.

出0入8汤圆

发表于 2022-7-4 11:46:20 来自手机 | 显示全部楼层
protothreads限制太多,变数又不可以stack(没机会用到内部reg组),又不可以太多嵌套subroutine,更改变了程序的正常结构。超简单program用一下还可以,但超简单program用main+interrupt不是更好吗?

出0入25汤圆

 楼主| 发表于 2022-7-4 12:01:20 来自手机 | 显示全部楼层
smallwood 发表于 2022-7-4 11:46
protothreads限制太多,变数又不可以stack(没机会用到内部reg组),又不可以太多嵌套subroutine,更改变了 ...
(引用自15楼)

pt内部如果需要复杂的操作可以  包成一个函数。然后对函数进行调用。

pt的好处是简单。适合初学者进行分析。 适合main  loop 进阶一下

出0入0汤圆

发表于 2022-7-4 14:16:40 | 显示全部楼层
看了MDK下编译后的汇编代码,这个运行效果纯属巧合,并且0级优化是这效果,3级优化就不是这效果,i>10后没有执行返回语句,所以结果随机

出0入0汤圆

发表于 2022-8-7 18:46:13 | 显示全部楼层
本帖最后由 cingljlw 于 2022-8-7 18:53 编辑

这里重新捋一下思路:
将main() 里面的printf改为:
printf("main() = %d\n",aa());

在aa()中sta = 1 ;前加入
printf("aa() = %d\n ",i);
将注释掉的return 6;改
printf("aa() end = %d\n ",i);

上述调试运行一下,你应该之就能知道为什么了和protothreads中case应用的精髓

出0入25汤圆

 楼主| 发表于 2022-8-8 10:33:05 | 显示全部楼层
已经基本吧PT消化完毕了。   回头来看 1楼写的问题,不是非常恰当。  

PT 的好处就是 PT_delay(100);假设函数里要等待 100ms 。 PT 是立马跳出这个函数,去执行另外的PT 函数。  当然 所有 包含 PT的函数, 都在一个 while(1){} 以内。  虽然PT 看起来很“恶心”(实际是 大神能工巧匠构思的东西)。但是 PT 确实够简单。  并没有打破 C语言的顺序执行的规则。   让人感觉到了多线程 的运行方式。

------------------------------------------

分析完毕PT 之后,   PT的优点即是缺点。  PT 是用 switch + static 变量来实现的。   所以PT语句的外面不能在继续 包 switch语句(禁止套娃)。   其他没什么限制,该怎么用 还是怎么用。

出0入42汤圆

发表于 2022-8-8 11:26:18 来自手机 | 显示全部楼层
rei1984 发表于 2022-8-8 10:33
已经基本吧PT消化完毕了。   回头来看 1楼写的问题,不是非常恰当。  

PT 的好处就是 PT_delay(100);假 ...

(引用自19楼)

套娃是指啥,比如一个任务的while1里,调用了一个函数,这个函数里可以用switch吗

出0入25汤圆

 楼主| 发表于 2022-8-9 11:21:21 | 显示全部楼层
我是一个大白菜 发表于 2022-8-8 11:26
套娃是指啥,比如一个任务的while1里,调用了一个函数,这个函数里可以用switch吗 ...
(引用自20楼)



PT常规的应用demo code:

void main()
{
        ....

        while(1)
        {
                aa();
                bb();
        }

}

void aa()
{

        do_something;
        pt_delay(100);

        do_something;
        pt_delay(100);

        do_something;
        pt_delay(100);


}

void bb()
{

        do_something;
        pt_delay(100);

        do_something;
        pt_delay(100);

        do_something;
        pt_delay(100);


}

实现的效果的,  aa() 非阻塞运行一会儿 ,然后 遇到 pt_delay(),立马运行 bb() . 当 bb()遇到 pt_delay() 。 立马 从  aa() 上次运行的语句 开始继续运行!。。  实现 类似于 threads 的效果。 由于 pt是采用 switch - case 来实现的。

所以如下代码是错误的:

void aa()
{

      switch( condition )
     {
               case xxx:
                       do_something;
                       pt_delay(100);
                       break;

                default:
                      break;



      }


}

以上代码就是涉及到套娃。 就不行了。 可能编译出错,或者 运行出错(不是你想要的结果)。

出0入42汤圆

发表于 2022-8-10 21:16:25 | 显示全部楼层
rei1984 发表于 2022-8-9 11:21
PT常规的应用demo code:

void main()
(引用自21楼)

非常感谢你的详细说明,现在明白了

出0入25汤圆

 楼主| 发表于 2022-8-10 22:29:24 | 显示全部楼层
我是一个大白菜 发表于 2022-8-10 21:16
非常感谢你的详细说明,现在明白了
(引用自22楼)

不客气。  这也是帮助自己。   

能把一件复杂的事情,说明白说清楚。  对自己的记忆理解也有好处

出0入0汤圆

发表于 2024-9-4 15:51:28 | 显示全部楼层
本帖最后由 Kwangsi 于 2024-9-4 15:55 编辑
rei1984 发表于 2022-8-10 22:29
不客气。  这也是帮助自己。   

能把一件复杂的事情,说明白说清楚。  对自己的记忆理解也有好处 ...
(引用自23楼)


楼主,我是不是踩坑里了

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-9-27 12:00

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表