技术论坛

 也来谈谈“先赋值后使用”!

返回主题列表
作者 主题
幸福的方向
侠士

经验值: 1154
发帖数: 232
精华帖: 0
楼主    2018-01-13 22:22:17
主题:也来谈谈“先赋值后使用”! 精编帖 

    对于临时变量的“先赋值后使用”大家都不会陌生,可是你是否真正正确地理解了“先赋值后使用”呢,我们来看看以下的例子:

    



通过仿真运行:I10.0=1,Q10.0=1 ,此时Q10.1=0属于先赋值后使用,彼此不受影响 ;

              I10.2=1,此时,Q10.1=Q10.6=Q10.7=1(q10.6和q10.7都受临时变量的影响,而且是受FC2内的临时变量影响,只因为FC2和FB1内的临时变量同名。)并且,尽管FB1调用时有DB块,也一样受临时变量影响,这是因为,FB1内使用的是临时变量,而非静态变量。

      若将图1FC2中并联的#run换成#run1,则,I10.0=1,q10.0,q10.1,q10.6,q10.7都将=1,也就是,后面的结果都受到临时变量的影响。

     以上弄明白了,我想“先赋值后使用”才算真正弄明白了。若有错误,敬请指正


雨过分洼种瓜,旱时饮水浇麻。
龚生
游士

经验值: 296
发帖数: 35
精华帖: 0
1楼    2018-01-13 22:30:30
主题:回复:也来谈谈“先赋值后使用”!

楼主,你这样分析问题真是误人子弟,看看你图二这样的写法就知道你的写法是错误的,懂吗?

幸福的方向
侠士

经验值: 1154
发帖数: 232
精华帖: 0
2楼    2018-01-13 22:50:25
主题:回复:也来谈谈“先赋值后使用”!

图2的写法是故意改成这样的,目的是为了试验,故意不用静态变量,而用的临时变量,是为了分析两种不同用法的不同结果...

雨过分洼种瓜,旱时饮水浇麻。
Haohaobb
至圣

经验值: 15850
发帖数: 1645
精华帖: 39
3楼    2018-01-13 23:40:18
精编帖  主题:回复:也来谈谈“先赋值后使用”!

自锁以及边沿触发的存储位是不能用temp的。

fc里面,如果就是为了演示而加了个run1可以理解,否则直接用run互锁就是了,另外,如果是博途,最好把run定义为inout,否则会有警告,当然也不影响使用。

fc里面的temp区和fb里面的temp区功能和特点是完全一样的,不明白演示第二个是什么意图。而且你可以发现fb里面的temp在背景db里面是没有的。

天道酬勤
幸福的方向
侠士

经验值: 1154
发帖数: 232
精华帖: 0
4楼    2018-01-13 23:57:41
精编帖  主题:回复:也来谈谈“先赋值后使用”!

“自锁以及边沿触发的存储位是不能用temp的。”开门见山,一针见血。的确这样,自锁如果用temp,立马就不是“先赋值后使用”了。

“而且你可以发现fb里面的temp在背景db里面是没有的。”这句也是一针见血啊,初学的时候,总以为FB是带DB块的,应该不存在“先赋值后使用”这个问题,后来才发现,DB块其实是为静态变量准备的,根本与temp无关。也就是无论FC还是FB,只要是临时变量,都要满足“先赋值后使用”这一条才不会出错。

很感谢,开眼界了。


雨过分洼种瓜,旱时饮水浇麻。
Letham
至圣

经验值: 13931
发帖数: 2006
精华帖: 43
5楼    2018-01-14 11:06:40
精编帖  主题:回复:也来谈谈“先赋值后使用”!

         I10.2=1,此时,Q10.1=Q10.6=Q10.7=1(q10.6和q10.7都受临时变量的影响,而且是受FC2内的临时变量影响,只因为FC2和FB1内的临时变量同名。

临时变量作用范围仅仅是在程序快内部,而已,不同程序块内部的临时变量是否同名没有任何关系。

临时变量在程序快调用结束后,内存会自动释放,所以 如楼上几位所说 ,比如上升沿等需要存储功能的指令是不能使用临时变量的。
当然,临时变量的使用,必须先赋值再使用的原则是不会错的

人生就像一场旅行!
幸福的方向
侠士

经验值: 1154
发帖数: 232
精华帖: 0
6楼    2018-01-14 12:15:27
主题:回复:也来谈谈“先赋值后使用”!

谢谢版主及时指正,临时变量应该是调用结束会释放的,下午有事,晚点再查一下。

雨过分洼种瓜,旱时饮水浇麻。
幸福的方向
侠士

经验值: 1154
发帖数: 232
精华帖: 0
7楼    2018-01-14 15:11:39
精编帖  主题:回复:也来谈谈“先赋值后使用”!

版主:发现个新情况,我重做了一下试验,为了简便,只做了一个FC1 和一个 FB1, DB为FB1的背景数据块。

FC1内run1为临时变量,FB1内run1也是临时变量。FC1和FB1内程序完全相同。

    OB1内无条件调用FC1和FB1,运行结果却是FC1和FB1内的临时变量是相互影响的。请看以下图片:





从试验结果来看,不同块中的临时变量好像是要相互影响的,怎么回事?

雨过分洼种瓜,旱时饮水浇麻。
幸福的方向
侠士

经验值: 1154
发帖数: 232
精华帖: 0
8楼    2018-01-14 16:16:51
精编帖  主题:回复:也来谈谈“先赋值后使用”!

    又试验了一下,这次把FB1内的临时变量改名为run2,运行结果也一样,是相互影响的。我再加了一个FB2,中间变量run1 用静态变量来代替,运行结果是FC1与FB1因为临时变量相互影响,而FB2因为用的是静态变量,不受其他两个影响。

    想了一下:临时变量调用后会保存调用后的结果,真正释放的是局部变量(如那些#start)。临时变量就像内存,调用后会留下上次使用的结果。这些内存是公用的,两个不同的块分别使用相同的内存(如FC1和FB1都是使用的一个位),而不管你给这个位起命为run1,还是run2,反正使用的都是公共内存的这个位,那么就会相互影响。这也正好就有了:临时变量必须“先赋值后使用”。

    很容易被麻痹,块调用结束临时变量不会释放,释放的是一些局部变量。

    

雨过分洼种瓜,旱时饮水浇麻。
emil128
侠圣

经验值: 3805
发帖数: 277
精华帖: 10
9楼    2018-01-15 10:04:35
精华帖  精编帖  主题:回复:也来谈谈“先赋值后使用”!

楼主实验做的是对的,可结论我看不懂。

“块调用结束临时变量不会释放,释放的是一些局部变量”???

什么是临时变量?什么是局部变量?各是什么地址类型?


1、每一个优先级都拥有属于自己的本地堆栈区(L区),所有运行在该优先级下的OB、FB、FC的Temp都属于该区域。

2、不同优先级的本地堆栈区不同,不会互相干扰。这是西门子从系统角度保证了各中断程序和主程序间的堆栈数据安全。

3、每次调用FB或FC其temp区域的本地堆栈地址由系统指定,调用结束释放(只是不再占用,并不清零)。所以FB或FC的调用可能会使用重合的本地堆栈,这也就是为什么temp不能跨周期传递的原因,于是所有需要跨周期传递的自保、边沿都不能用temp。


L 堆栈永远以地址“0”开始。 
在 L 堆栈中,会为每个数据块保留相同个数的字节,作为存放每个块所拥有的静态或局部数据。
当某个块终止时,那么它的空间随之也被重新释放出来。

指针总是指向当前打开块的第一个字节。



看雪001
至圣

经验值: 19338
发帖数: 2076
精华帖: 72
10楼    2018-01-15 10:25:46
精编帖  主题:回复:也来谈谈“先赋值后使用”!

你也可以使用“代入法”,将输入输出接口全部替换为实参,象下面这样:

这样演化一下,可以撇开块接口的干扰,将“临时变量”等同于“双线圈”来看待。观察“双线圈”在一个扫描周期内的逻辑变化情况,梯形图虽然形式上看上去象继电逻辑,但它是扫描执行,不等于继电逻辑。


大道至简,知易行难
您收到0封站内信:
×
×
信息提示
很抱歉!您所访问的页面不存在,或网址发生了变化,请稍后再试。