Tinygo是一种比较方便的开发语言,虽然适应面有限,但go语言实在是太方便,而且tinygo编译后的代码非常小,有时候我们直接用它来取代c做嵌入式开发,本篇就是介绍了某次在使用tinygo开发,因类型转换产生的错误。
#申请原创#
我们知道在嵌入式开发中,因为内存有限,往往希望把变量类型尽可能设置够用就行,比如我们的变量是1~200,我们往往希望只用一个uint8来表示这个变量。而tinygo在首次定义变量并且赋值时,如果不指定类型,会直接将变量设置为int类型。在tinygo中,不支持不同类型的数字进行相互赋值或运算,只能通过函数强制转换后再使用。
例如:
u:=-5
var v uint8=uint8(u)
v会根据u的二进制表示,直接截取后8位,得到结果251。或者直接简写为v:=uint(u)即可。
类似的,
u:=500
v:=uint8(u)
v可以得到值为244的无符号8位整形。
这种用法已经非常普遍了,但某次我在调程序的时候,发现如果不设置变量u,直接将v进行赋值,则会出现错误。
如v:=uint8(int(-1))
编译时,会直接提示overflow了。
关于这个问题,我找了不少资料,大多数资料都没有说清楚原因,直到有一天,我重温汇编语言时,才终于领悟。
对于一个变量u,程序会給它规划出一个地址空间,根据变量的类型,可能会是8位、16位、32位,这个地址空间内的数值可以在程序运行过程中,因变量赋值或者运算而发生改变,但地址本身相对不变。当我们执行类似v:=uint8(u)代码时,实际上是把空间中的数值(或者其中一部分)拷贝一份到新的位置,类似于汇编中的直接寻址。
对于一个固定的数字(比如上面的-1),在内存中分配的是一个临时的空间,比如[234h],它的值是0xffffffff,当我们执行类似v:=uint8(int(-1))代码时,将临时空间的数值强行塞入分配的空间,如果碰巧数字在待赋值的变量范围内,可以实现自动转换,如果出现超出变量数据类型能够支撑的范围,则无法赋值成功。这种有点类似汇编语言中的立即寻址,寻址命令完成后,数字的临时空间立刻被销毁,下次即使是再次赋值相同数字,地址空间也不一样。
对于go语言的学习,需要耐心和细心,对于嵌入式板上使用的tinygo,更是如此,任何细节都有可能影响到整个系统。
@21小跑堂 |