找回密码
 立即注册
楼主: Shoteen

关于C251内核结构体定义区域的问题

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:5
  • 最近打卡:2025-04-30 07:46:22

33

主题

1079

回帖

2319

积分

荣誉版主

积分
2319
发表于 2024-10-26 13:08:59 | 显示全部楼层
本帖最后由 tzz1983 于 2024-10-26 13:10 编辑
Cos*** 发表于 2024-10-26 12:05
刚才我也做了一些实验,在类型定义中写 存储域,都能符合预期。
当年我碰到异常的情况想不起来了,等想起 ...

我觉得我们可以开个新帖来总结 Keil C251 的一些特殊之处,
特别是会出现编译BUG的情况,大家把自己遇到的情况汇集起来,避免重复踩坑。

我现在能回忆起来的关于Keil C251几点:
1. AI8051U刚出来时,好像是“大明狐” 那个代码,出现编译错误重启,链接器把一个函数的调用地址定位到0x0000,
具体是什么情况得回头贴了。(这个应该是算比较严重的,原因暂未查明,或许和用LIB库或 LX链接器 或REMOVEUNUSED 指令相关)
2. 指针和整形之间强制互转时,极少情况会出现丢失高位字节,这个事情我在你主帖中曾经说起过。
3. 前几天遇到一个坑,大至描述如下:
char  i;   //全局变量
void test(void)
{
    i=0;
    while(i==0);  //等待某个中断给i重新赋值1;
}
运行结果是,在while处根本就不判断i的值,直接返回了,很郁闷,让我好找啊。
后来想到,这个应该不算是BUG,算是一个坑吧,定义变量前加 volatile , 或者降低优化等级至5,就可以避免错误。
4. 据论坛内某些帖说,Keil C251 局部变量不能定义数组,可能会出现未知的错误,关于这一条,我从来没有遇到过,或许是谣传。

点评

我给你找到了一个示例, typedef 中指定 存储域,可能出现的一些情况: typedef struct { u32 a; float b; }mmm_ts; typedef mmm_ts xdata * data mmm_tsp; // 类型定义时指定 mmm_tsp 的存储域为 data 1  详情 回复 发表于 2024-10-26 14:41
我休息了一段时间,最近又开始新一轮的征程了。 当前正在调整 CosyOS 代码中的 空格、tab 等,添加丰富的注释, 并同时查找 bug。 有必要开一贴总结 C51、C251 的 bug,或者说 是 编译器特性, 使用中应注意的地方  详情 回复 发表于 2024-10-26 13:44
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:432
  • 最近打卡:2025-05-01 16:19:56

5

主题

1127

回帖

4263

积分

荣誉版主

积分
4263
发表于 2024-10-26 13:44:58 | 显示全部楼层
tzz1*** 发表于 2024-10-26 13:08
我觉得我们可以开个新帖来总结 Keil C251 的一些特殊之处,
特别是会出现编译BUG的情况,大家把自己遇到 ...

我休息了一段时间,最近又开始新一轮的征程了。
当前正在调整 CosyOS  代码中的 空格、tab 等,添加丰富的注释,
并同时查找 bug。
有必要开一贴总结 C51、C251 的 bug,或者说 是 编译器特性,
使用中应注意的地方,如 你提到的 需要加 volatile 的情况。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:432
  • 最近打卡:2025-05-01 16:19:56

5

主题

1127

回帖

4263

积分

荣誉版主

积分
4263
发表于 2024-10-26 14:41:57 | 显示全部楼层
本帖最后由 CosyOS 于 2024-10-26 14:56 编辑
tzz1*** 发表于 2024-10-26 13:08
我觉得我们可以开个新帖来总结 Keil C251 的一些特殊之处,
特别是会出现编译BUG的情况,大家把自己遇到 ...

我给你找到了一个示例,
typedef 中指定 存储域,可能出现的一些情况:

typedef struct
{
    u32 a;
    float b;
}mmm_ts;
typedef mmm_ts xdata * data
mmm_tsp; // 类型定义时指定
mmm_tsp 的存储域为 data

1、
定义单一变量、未指定存储域
mmm_tsp mmm;
C51/C251:均由 类型定义中的存储域决定,为 data。


2、定义单一变量、指定了与类型定义中不同的存储域
mmm_tsp xdata mmm;
C51:告警 C185;
C251:error C77。


3、定义数组变量、未指定存储域
mmm_tsp mmm[2];

C51:将完全由 内存model 决定
存储域,不鸟 类型定义中的存储域;
C251:由 类型定义中的存储域决定,为 data。


4、
定义数组变量、指定了与类型定义中不同的存储域
mmm_tsp xdata mmm[2];

C51/C251:均不会产生告警或错误,并由此处的存储域决定,即 xdata。


可见,在类型定义中指定存储域,一般情况下不会出问题,能够符合预期;

但在一些特殊情况下,可能会超出预期,搞出一些莫名其妙的故障。
在类型定义中指定存储域确实方便应用,
但用户应认识到其中可能存在的风险。



点评

另外我也发现了,指针类型确实没有符合原有期望。 比如: struct { /* 成员定义;*/ }xdata BUTTON; BUTTON * pt; 从主观理解来说,pt是(xdata*)类型,应该是2字节。 而实际上, sizeof(pt) == 4, 与预期  详情 回复 发表于 2024-10-26 16:18
好的,挺详细的,感谢分享 我的理解是,对于第二点,可以理解为重复设定域,即便是data, 也会出现错误或警告,这是人为制造二义错误,与编译无关。 第三和第四,层次太深了哈,编译器理解不了, Keil C251 我也有点  详情 回复 发表于 2024-10-26 15:51
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:5
  • 最近打卡:2025-04-30 07:46:22

33

主题

1079

回帖

2319

积分

荣誉版主

积分
2319
发表于 2024-10-26 15:51:05 | 显示全部楼层
本帖最后由 tzz1983 于 2024-10-26 15:56 编辑
Cos*** 发表于 2024-10-26 14:41
我给你找到了一个示例,
typedef 中指定 存储域,可能出现的一些情况:

好的,挺详细的,感谢分享
我的理解是,对于第二点,可以理解为重复设定域,即便是data, 也会出现错误或警告,这是人为制造二义错误,与编译无关。
第三和第四,层次太深了哈,编译器理解不了, Keil C251 我也有点感觉它 “年久失修”了,不过凑合用还是不错的。

另外,如果层次不这么深,数组还是可以用的。比如实际项目代码:
截图202410261539591976.jpg

截图202410261543065204.jpg


我一直都这样用,很方便, 定义数组时不用刻意去指定edata,  
不管是采用哪种MemModel, 最终栈都是定位在edata.

另外,我支持你的说法,在没有特殊个人偏好的情况下,就好用标准的方法。以避免无畏的错误。  
从理论上来说,数据结构体描述的是数据结构本身,它和存储域确实没什么关系的。


点评

我们通过类举这些示例,证明在特殊情况下, 类型定义中指定存储域,可能会出现一些问题, 用户自己斟酌。 CosyOS 源码中就有大量的这种深层次定义, 当年在 C51下开发时,一开始就是在类型定义中指定存储域, 出现了  详情 回复 发表于 2024-10-26 16:14
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:432
  • 最近打卡:2025-05-01 16:19:56

5

主题

1127

回帖

4263

积分

荣誉版主

积分
4263
发表于 2024-10-26 16:14:48 | 显示全部楼层
tzz1*** 发表于 2024-10-26 15:51
好的,挺详细的,感谢分享
我的理解是,对于第二点,可以理解为重复设定域,即便是data, 也会出现错误或警 ...

我们通过类举这些示例,证明在特殊情况下,
类型定义中指定存储域,可能会出现一些问题,
用户自己斟酌。
CosyOS 源码中就有大量的这种深层次定义,
当年在 C51下开发时,一开始就是在类型定义中指定存储域,
出现了各种问题,后来才改为一律在定义变量时指定存储域。

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:5
  • 最近打卡:2025-04-30 07:46:22

33

主题

1079

回帖

2319

积分

荣誉版主

积分
2319
发表于 2024-10-26 16:18:32 | 显示全部楼层
Cos*** 发表于 2024-10-26 14:41
我给你找到了一个示例,
typedef 中指定 存储域,可能出现的一些情况:

另外我也发现了,指针类型确实没有符合原有期望。
比如:
struct
{
    /* 成员定义;*/
}xdata BUTTON;

BUTTON  * pt;

从主观理解来说,pt是(xdata*)类型,应该是2字节。
而实际上, sizeof(pt) == 4,  与预期不符。

点评

你这个例子很好 !!!  发表于 2024-10-26 16:20
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:422
  • 最近打卡:2025-05-01 09:54:52
已绑定手机

19

主题

3190

回帖

4866

积分

论坛元老

积分
4866
发表于 2024-10-26 17:34:39 | 显示全部楼层
C251内核结构体定义区域还有这么多规则啊
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看II
  • 打卡总天数:28
  • 最近打卡:2025-01-08 16:11:02

12

主题

26

回帖

224

积分

中级会员

积分
224
发表于 2024-10-28 14:30:36 | 显示全部楼层
tzz1*** 发表于 2024-10-26 08:17
没有仔细看代码,不知道为什么产生不可预料的仰错误,可以降低优化等级,关掉全局重入选项试试。

在结构体 ...

感谢大佬解答! 我这就去试试!
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看II
  • 打卡总天数:28
  • 最近打卡:2025-01-08 16:11:02

12

主题

26

回帖

224

积分

中级会员

积分
224
发表于 2024-10-28 14:31:13 | 显示全部楼层
Cos*** 发表于 2024-10-26 08:42
类型定义时,写 存储域 是无效的,最终结果不会符合你的预期。
存储域是变量的存储域,只有在定义变量时写 ...

感谢大佬解答!我这就去试试
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 02:32 , Processed in 0.120630 second(s), 105 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表