🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
【37.1 不同类型变量的赋值疑惑。】 之前讲过,多字节变量赋值给单字节变量时,多字节变量的低8位直接覆盖单字节变量,这个很容易理解,比如: unsigned long a=0x12345678; //多字节变量 unsigned char t=0xab; //单字节变量 t=a; //多字节赋值给单字节变量,t的结果由原来的0xab变成了0x78 那么,问题来了,如果调换过来,单字节赋值给多字节变量,多字节变量除了低8位被单字节变量所直接覆盖之外,其它剩余的位会是什么状态?会被0覆盖吗?还是会保持原来的数值不变?这个就是本节将要解开的疑惑。比如: unsigned long a=0x12345678; //多字节变量 unsigned char t=0xab; //单字节变量 a=t; //单字节赋值给多字节变量,此时,a到底是0x123456ab?还是0x000000ab?疑惑中...... 想解开此疑惑,只要亲自上机测试一下就知道结果。经过在Keil平台下的C51编译器测试后,发现结果是这样子的:a是0x000000ab!也就是说,多字节变量其余高位是默认被0覆盖的。但是,我还有一个疑惑,是不是所有的C编译器都是这样默认处理,会不会在不同的C编译器平台下,会有不同的结论?所以,下面我再介绍两种比较可靠的办法给大家。 【37.2 我以前用的办法。】 我以前做项目的时候,每逢遇到这个疑惑,在不同变量赋值之前,我都多插入一行清零的代码,这行代码就是先把多字节变量通过直接赋值0来清零,因为我确信常量赋值都是直接覆盖的(其余高位都直接用0填充)。比如: unsigned long a=0x12345678; //多字节变量 unsigned char t=0xab; //单字节变量 a=0; //赋值之前先清零,这是我以前用的办法。 a=t; //单字节赋值给多字节变量 现在反省了一下,这种办法虽然可靠实用,但是显得过于保守。 【37.3 我现在用的办法:C语言类型的强制转换。】 前面章节提到,括号在C语言中有强制的意思,可以强制改变优先级,也可以强制促进不同变量类型的匹配。比如: unsigned long a=0x12345678; //多字节变量 unsigned char t=0xab; //单字节变量 a=(unsigned long)t; //此处的括号就是强制把t先转变成unsigned long类型,然后再赋值。 这是我现在所使用的办法,推荐大家用这种。 【37.4 例程练习和分析。】 现在编写一个程序来验证刚才讲到的主要内容: 程序代码如下: /\*---C语言学习区域的开始。-----------------------------------------------\*/ void main() //主函数 { unsigned long a=0x12345678; //多字节变量 unsigned long b=0x12345678; unsigned long c=0x12345678; unsigned char t=0xab; //单字节变量 a=t; //a是0x000000ab,其余高位默认被0覆盖。 b=0; //这是我以前用的办法,显得过于保守 b=t; c=(unsigned long)t; //C语言的类型强制转换。现在推荐大家用这种。 View(a); //把第1个数a发送到电脑端的串口助手软件上观察。 View(b); //把第2个数b发送到电脑端的串口助手软件上观察。 View(c); //把第3个数c发送到电脑端的串口助手软件上观察。 while(1) { } } /\*---C语言学习区域的结束。-----------------------------------------------\*/ 在电脑串口助手软件上观察到的程序执行现象如下: 开始... 第1个数 十进制:171 十六进制:AB 二进制:10101011 第2个数 十进制:171 十六进制:AB 二进制:10101011 第3个数 十进制:171 十六进制:AB 二进制:10101011 分析: 通过实验结果,发现在单片机上的实验结果和我们的分析是一致的。 【37.5 如何在单片机上练习本章节C语言程序?】 直接复制前面章节中第十一节的模板程序,练习代码时只需要更改“C语言学习区域”的代码就可以了,其它部分的代码不要动。编译后,把程序下载进带串口的51学习板,通过电脑端的串口助手软件就可以观察到不同的变量数值,详细方法请看第十一节内容。