前言:在写程序时候遇到了一些关于数据类型转换的问题,编译器也没有报错,运行时才发现数据不对,找bug花费了很多时间,但最终也发现是一些细节上的问题,特地在这里整理出一篇文章记录。

实验环境:

芯片架构:Cortex-M0+

开发IDE:Keil_v5

编译器:armcc

问题代码:

uint64_t TempData2;

uint8_t KeyeBuf1[8];

TempData2 = ( KeyeBuf1[0] + (KeyeBuf1[1] << 8) + (KeyeBuf1[2] << 16) + (KeyeBuf1[3] << 24)+

(KeyeBuf1[4] << 32) + (KeyeBuf1[5] << 40) + (KeyeBuf1[6] << 48));

在上述代码中,先前已经声明了TempData2的数据类型为无符号64位整型类型,在接下来的移位后累加数据总是出现差错,检查累加后数据范围也没有超过无符号64位整型数据范围。

问题分析:

经过一系列的排查,最终发现了问题所在,主要是以下三方面造成的影响:

1.机器平台与编译器的影响

stdint.h是C99中引进的一个标准C库的文件,目前大部分单片机的C编译器均支持。关于编译器支的更多数据类型完全可以在该文件中找到。以armcc编译器为例,文件中,对于8位,16位,32位,64位无符号整数类型的数据定义为如下:

#include

uint64_t TempData2;

typedef unsigned char uint8_t;

typedef unsigned short int uint16_t;

typedef unsigned int uint32_t;

typedef unsigned __INT64 uint64_t;

查找该文件可得uint64_t的类型是unsigned __INT64类型,__INT64类型的解释与机器平台和编译器相关。

机器平台的硬件架构以及编译器的编译最终都会影响执行代码的生成。Cortex-M0+是32位的处理器,内部的寄存器大多都是32位,这就导致了在默认情况下进行的运算,不管是8位,16位,32位都在32位寄存器中运算。

2.“=”符号运算顺序的影响

=符号的执行过程细分下来可以分成两步:

计算=右边部分得出最终结果

最后把结果赋给=左边变量

由于上述的运算顺序导致,=左边变量不管原先定位为多少位,对先执行的=右边计算过程没有影响,也就是说,在上述代码过程中,即使左边变量先定义为64位,在先进行右边部分计算时,还是按照右边部分数据最大的数据类型来数据对齐,而后进行计算。

3.移位程序移植性的影响

对于移位程序来说,右移数据基本不会出太大问题,但是左移就需要注意很多。在32位机器平台上,8位,16位,32位数据类型都会在32位寄存器中进行移位,只要我们确保移位后的数据不会超过32位数据类型,那么程序就会正常运行。而上述数据类型一旦移位后的数据类型超过32位,那么处理器会丢失左移向前进的数据,留下最低的32位。

问题解决:

对于上述代码进行分析,( KeyeBuf1[0] + (KeyeBuf1[1] << 8) + (KeyeBuf1[2] << 16) + (KeyeBuf1[3] << 24)+ (KeyeBuf1[4] << 32) + (KeyeBuf1[5] << 40) + (KeyeBuf1[6] << 48));中的Keye1数组数据类型都是8位,计算时都在32位寄存器中计算。前几个数据的移位没有超过32位数据类型不会出太大错误,从(KeyeBuf1[4] << 32)起,理论上移位后的数据超过了32位,只留下最低32位,导致数据出错。即使最后赋给了一个64位的变量,也是将一个32位数据赋给64位,而这些问题在编译时期编译器并不会指出,需要我们自己多加注意。

最后的解决方法是将KeyeBuf1数据在运算时强制转换为64位数据类型,这样进行运算时都是64位数据对齐,最后赋给一个64位数据类型,就不会出现数据丢失的情况了。代码如下:

TempData2 = ( KeyeBuf1[0] + (KeyeBuf1[1] << 8) + (KeyeBuf1[2] << 16) + ((uint64_t)KeyeBuf1[3] << 24)+

((uint64_t)KeyeBuf1[4] << 32) + ((uint64_t)KeyeBuf1[5] << 40) + ((uint64_t)KeyeBuf1[6] << 48));

c语言变量强制转换,C语言——“=”中的强制类型转换相关推荐

  1. c语言首字母大小写字母转换,C语言大小写字母转换,C语言 大小写字母转换

    导航:网站首页 > C语言大小写字母转换,C语言 大小写字母转换 C语言大小写字母转换,C语言 大小写字母转换 匿名网友: #includevoid main(){char c1,c2: // ...

  2. 哪些不符合python语言变量名_以下选项中不符合 Python 语言变量命名规则的是( )_学小易找答案...

    [单选题]下列各项中,关于银行存款业务的表述中正确的是( ).(2012年) [单选题]下列各项中,关于企业无法查明原因的现金溢余,经批准后应贷记的会计科目是( ). [多选题]计价软件中,在人材机汇 ...

  3. c语言 存储管理地址转换,C语言地址的强制转换

    地址的强制转换 先看下面这个例子: struct Test { int Num; char *pcName; short sDate; char cha[2]; short sBa[4]; }*p; ...

  4. c语言变量加常量,C语言(二)---常量与变量(示例代码)

    一.进制 1.1 二进制 1.1 简介 二进制数据是用0和1两个数码来表示的数.它的基数是2,进位规则是"逢二进1",借位规则是"借一当二".当前的计算机系统使 ...

  5. 无效的变量名c语言,变量方法用法 _C语言-w3school教程

    C语言 的 变量 变量是内存位置的名称.它用于存储数据.其值可以更改,可以重复使用多次. 它是通过符号表示内存位置的方法,以便可以容易识别. 我们来看一下声明一个变量的语法: type variabl ...

  6. python语言变量名规则_python语言变量命名规则

    Python语言变量命名规则 变量名只能包含字母.数字和下划线.(推荐学习:Python视频教程) 变量名可以字母或下划线开头,但不能以数字开头.例如,可将变量命名为message_1,但不能将其命名 ...

  7. C语言变量初始化作用,C语言变量初始化

    C语言变量初始化教程 如果是定义的 因此,在 C 语言中,一个很好的习惯就是在定义变量的同时,给变量初始化,也就是给变量一个默认值. C语言变量初始化详解 语法 type varname = valu ...

  8. python强制转换整数_python数据类型的强制转换

    数据类型的强制转换 如果要将一个数据转换成另一个数据类型,只需要将其放入相应类型的函数中去. Number类型的数据转换 强制转换为int 可以转换的数据类型 int 整型 float 浮点型 boo ...

  9. java数据类型的转换函数_JAVA中常用数据类型转换函数

    JAVA中常用数据类型转换函数: string->byte Byte static byte parseByte(String s) byte->string Byte static St ...

最新文章

  1. linux 变量获取问题,有关read命令从管道输出读取变量参数的问题
  2. 滴滴算法大赛算法解决过程 - 机器学习
  3. 成功解决Exception unhandled OSError cannot open resource File: F:\Program Files\Python\Python36\Lib\si
  4. 配置阿里巴巴的数据源
  5. XAMPP——Apache不能启动解决方案
  6. ILRuntime_NewbieGuide—入门
  7. python 输入中文_【提醒】Python新手开发人员注意事项:不要误输入中文标点符号...
  8. mysql for CodeSmith
  9. python入门环境准备_python入门 之 环境配置(一)
  10. 【IDEA系列】利用 IntelliJ IDEA 进行代码对比的方法
  11. myeclipse使用(技术和快捷键)
  12. 全球首个大规模虐童图像数据库!标记15万图像、20类信息,自动判断图片是否违法​...
  13. 女性养生最需要的十种食物
  14. 2022年12月10日作业
  15. Python三维地址建模教程【Gempy】
  16. 37互娱笔试智力题--猜帽子问题分析
  17. IEC61499标准背后的逻辑
  18. Java项目:眼镜商城系统(java+SSM+JSP+jQuery+Mysql)
  19. 国家级专新特精“小巨人”「皖仪科技」携手企企通,打造采购数字化平台成功上线
  20. Elasticsearch - 是什么,以及应用场景

热门文章

  1. python3类的继承详解_基于python3 类的属性、方法、封装、继承详解
  2. wedo2.0编程模块介绍_福特福克斯TCM重新编程操作
  3. linux 建立交叉编译环境变量,ARM-Linux-gcc-4.4.3交叉编译环境终于搭建
  4. JAVA不同类型数组重载_java学习笔记--java中的方法与数组
  5. 计算机本科毕业设计:毕业设计、论文要点及我们面对毕业答辩应持有的态度
  6. Eclipse 答疑:为什么 Eclipse 里面的鼠标光标变成了小黑方块?什么原因导致的?
  7. 如何使用 MySQL 的 IDE 导出导入数据表文件(以 Navicat for MySQL 导出导入 Excel 文件为例)
  8. php时分获取秒数,javascript与php时/分/秒与秒数互转
  9. 华为畅享max有没有人脸识别_华为畅享7s有人脸识别吗 让我来告诉你
  10. 线程池拒绝策略 开发中常用什么策略_面试官:说说你知道多少种线程池拒绝策略...