当前位置: 首页 > java >正文

C语言类型转换踩坑解决过程

问题背景

开发环境

  • IDE: CCS (Code Composer Studio)
  • 编译器: TI v20.12.0 STS
  • ABI: COFF
  • CPU: TMS320F8377D C28x
  • 场景: CPU 核间通信队列
    在初始化一个 CPU 核间通信的队列时,我发现队列大小的计算出现了异常。起初问题看似出现在初始化代码段,但经过抽离和调试,我发现核心问题在于计算队列大小的宏定义。

问题如下,我将出现问题的代码抽离处理调试了任然出现计算值和理想值不同,如下var1 我觉得是1,但是却为68,最终确定是size_t的问题,可是我还是不知道怎么算出来的68:

Case1

volatile uint16_t w = 0;
volatile uint16_t r = 138;struct A_t{uint16_t var[22];};
#define SIZE_XX ((1024 * 3) / sizeof(struct A_t)) //139volatile int16_t var1 = (w - r + SIZE_XX) % SIZE_XX;volatile int16_t var2 = (w - r);volatile int16_t var3 = (w - r + SIZE_XX);volatile int16_t var4 = (var2 + SIZE_XX);volatile int16_t var5 = (var2 + SIZE_XX) % SIZE_XX;volatile int16_t var6 = var3 % SIZE_XX;

在TMS320F8377D上面使用CCS调试运行可以看到变量的值为,var1 的值预期应该为1,但是实际却为68,不符合预期:

var1 : 68
var2 : -138
var3 : 1
var4 : 1
var5 : 1
var6 : 1

但是如果我将这个队列缓存长度的宏定义改成这样就没问题了:

Case2

volatile uint16_t w = 0;
volatile uint16_t r = 138;struct A_t{uint16_t var[22];};
#define SIZE_XX ((1024 * 3) / 22)  //139volatile int16_t var1 = (w - r + SIZE_XX) % SIZE_XX;volatile int16_t var2 = (w - r);volatile int16_t var3 = (w - r + SIZE_XX);volatile int16_t var4 = (var2 + SIZE_XX);volatile int16_t var5 = (var2 + SIZE_XX) % SIZE_XX;volatile int16_t var6 = var3 % SIZE_XX;

在TMS320F8377D上面使用CCS调试运行可以看到变量的值为,均符合预期:

var1 : 1 
var2 : -138
var3 : 1
var4 : 1
var5 : 1
var6 : 1

即使#define SIZE_XX ((1024 * 3) / 22U)也是符合预期的。
就是使用sizeof后就不对了,我的认知中sizeof是返回size_t类型的值,于是我将SIZE_XX改为#define SIZE_XX ((1024 * 3) / (size_t)22)出现了Case1中的问题。

我又去看了TI的编译器中size_t的定义,两个文件中的定义均如下:

//stddef.h 
#ifndef _SIZE_T_DECLARED
#define _SIZE_T_DECLARED
# ifdef __clang__
typedef __SIZE_TYPE__ __SIZE_T_TYPE__;
# endiftypedef __SIZE_T_TYPE__ size_t;
#endif
//STDIO.H 
#ifndef _SIZE_T_DECLARED
#define _SIZE_T_DECLARED
#ifdef __clang__
typedef __SIZE_TYPE__ size_t;
#else
typedef __SIZE_T_TYPE__ size_t;
#endif
#endif

可是__SIZE_T_TYPE__是什么,我在《TMS320C28x Optimizing C/C++ Compiler
v20.12.0.STS》https://www.ti.com.cn/cn/lit/ug/spru514v/spru514v.pdf中只看到了__SIZE_T_TYPE__的描述为Set to the type of size_t(位于37页),但是没有找到__SIZE_T_TYPE__的具体行为和实现。

我只知道size_t是C中任何对象所能达到的最大长度,它是无符号整数。但是具体是多大不知道,手册也没写,于是我想到了通过limits.h看看size_t的范围,如下:

/* Limit of size_t. */
#if !defined(__TMS320C28XX_CLA__)
#define	SIZE_MAX	UINT32_MAX
#else
#define	SIZE_MAX	UINT16_MAX
#endif

可以看到TI的这个编译器中size_t是32bit的无符号数,于是我将将SIZE_XX改为#define SIZE_XX ((1024 * 3) / (uint32_t)22)出现了Case1中的问题。可是我还是无法理解问题到底出在哪里。
我知道TI的C28x的编译器中一个字节是16bit的,默认的int类型实际为int16_t,SIZE_XX 得到的结果类型为size_t->uint32_t,我按照这个来计算volatile uint32_t var3_u32 = (w - r + SIZE_XX);->var3_u32 = 65537,于是65537 Mod 139 = 68。

具体来说:

表达式 (w - r) 的类型为uint16_t,所以var2_u16为65398
表达式 (w - r + SIZE_XX) = (65398u16+139u32) = 65537u32
所以 (w - r + SIZE_XX) % SIZE_XX = 65537u32 % 139u32 = 68u32volatile uint32_t var3_u32 = (w - r + SIZE_XX);
volatile uint16_t var2_u16 = (w - r);
volatile uint16_t var3_u16 = (w - r + SIZE_XX);
http://www.xdnf.cn/news/19296.html

相关文章:

  • 重叠IO模型
  • 深入理解 Linux 驱动中的 file_operations:从 C 语言函数指针到类比 C++ 虚函数表
  • 学习Python中Selenium模块的基本用法(11:弹窗处理)
  • Day18_【机器学习—交叉验证与网格搜索】
  • 【ROS2】ROS2 基础学习教程 、movelt学习
  • PostgreSQL 数据库灾备要点与举例说明**
  • Spring Data Redis 的使用方法
  • 电子战:多功能雷达工作模式识别
  • [光学原理与应用-339]:ZEMAX - Spot Diagram(点列图)是评估光学系统成像质量的核心工具,它通过几何光线追迹直观展示像差对成像的影响。
  • 模拟实现STL中的list容器
  • 行内元素块元素
  • Coze源码分析-API授权-添加新令牌-后端源码
  • mysql权限user表赋权操作修改
  • 【大语言模型 30】指令微调数据工程:高质量数据集构建
  • 计算机算术7-浮点基础知识
  • 面试tips--MyBatis--<where> where 1=1 的区别
  • Burgan Bank Türkiye 如何借助 Elastic 改造可观测性和安全性
  • 【LeetCode 热题 100】62. 不同路径——(解法四)组合数学
  • Scikit-learn Python机器学习 - Scikit-learn加载数据集
  • 49.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--扩展功能--集成网关--Refit跨服务调用
  • Photoshop - Ps Camera Raw 滤镜
  • 爱普生L3255打印机故障记录
  • 算法(②排序算法)
  • 在word以及latex中引用zotero中的参考文献
  • JVM架构图是怎样的?
  • Python - 机器学习:从 “教电脑认东西” 到 “让机器自己学规律”
  • 第7.5节:awk语言 switch 语句
  • Kubernetes 部署与发布完全指南:从 Pod 到高级发布策略
  • Ruoyi-vue-plus-5.x第一篇Sa-Token权限认证体系深度解析:1.3 权限控制与注解使用
  • Python爬虫实战:构建Widgets 小组件数据采集和分析系统