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

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.dtcms.com/a/359114.html

相关文章:

  • Java高并发架构核心技术有哪些?
  • 安装Redis
  • compute:古老的计算之道
  • 【ROS2】ROS2 基础学习教程 、movelt学习
  • Docker实战避坑指南:从入门到精通
  • plantsimulation知识点 多条RGV驮一台工件图标显示顺序问题
  • lumerical_FDTD_光源_TFSF
  • 【AI】【强化学习】强化学习算法总结、资料汇总、个人理解
  • php连接rabbitmq例子
  • SpringCloud学习笔记
  • 大模型应用开发面试全流程实录:RAG、上下文工程与多Agent协作技术深度解析
  • ABAP 刷新屏幕
  • 【C++】日期类实现详解:代码解析与复用优化
  • BEV-VAE
  • 3000. 对角线最长的矩形的面积
  • 配置vsc可用的C语言环境
  • Linux系统统计用户登录和注销时间的工具之ac
  • Dify的搭建
  • Glato - AI 驱动的广告视频创作平台
  • [光学原理与应用-329]:ZEMAX - 主要用途与主要功能
  • Python爬虫实战:研究统计学方法,构建电商平台数据分析系统
  • Windows驱动开发与双机调试环境[驱动开发环境配置高阶]
  • [创业之路-582]:评估难易程度、重要程度,站在不同的角度有不同的答案
  • 第09章 t检验:两独立样本t检验
  • 【MCP系列教程】 Python 实现 FastMCP StreamableHTTP MCP:在通义灵码 IDE 开发并部署至阿里云百炼
  • 49.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--扩展功能--集成网关--Refit跨服务调用
  • java中的VO、DAO、BO、PO、DO、DTO
  • 操作系统-虚拟内存篇
  • 数据结构(顺序表力扣刷题)
  • 使用 Visio Viewer 查看 Visio 绘图文件