CosyOS 发表于 2024-10-26 12:05
刚才我也做了一些实验,在类型定义中写 存储域,都能符合预期。
当年我碰到异常的情况想不起来了,等想起 ...
我觉得我们可以开个新帖来总结 Keil C251 的一些特殊之处,
特别是会出现编译BUG的情况,大家把自己遇到的情况汇集起来,避免重复踩坑。
我现在能回忆起来的关于Keil C251几点:
1. AI8051U刚出来时,好像是“大明狐” 那个代码,出现编译错误重启,链接器把一个函数的调用地址定位到0x0000,
具体是什么情况得回头贴了。(这个应该是算比较严重的,原因暂未查明,或许和用LIB库或 LX链接器 或REMOVEUNUSED 指令相关)
2. 指针和整形之间强制互转时,极少情况会出现丢失高位字节,这个事情我在你主帖中曾经说起过。
3. 前几天遇到一个坑,大至描述如下:
chari; //全局变量
void test(void)
{
i=0;
while(i==0);//等待某个中断给i重新赋值1;
}
运行结果是,在while处根本就不判断i的值,直接返回了,很郁闷,让我好找啊。
后来想到,这个应该不算是BUG,算是一个坑吧,定义变量前加 volatile , 或者降低优化等级至5,就可以避免错误。
4. 据论坛内某些帖说,Keil C251 局部变量不能定义数组,可能会出现未知的错误,关于这一条,我从来没有遇到过,或许是谣传。
tzz1983 发表于 2024-10-26 13:08
我觉得我们可以开个新帖来总结 Keil C251 的一些特殊之处,
特别是会出现编译BUG的情况,大家把自己遇到 ...
我休息了一段时间,最近又开始新一轮的征程了。
当前正在调整 CosyOS代码中的 空格、tab 等,添加丰富的注释,
并同时查找 bug。
有必要开一贴总结 C51、C251 的 bug,或者说 是 编译器特性,
使用中应注意的地方,如 你提到的 需要加 volatile 的情况。
本帖最后由 CosyOS 于 2024-10-26 14:56 编辑
tzz1983 发表于 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;
C51:将完全由 内存model 决定存储域,不鸟 类型定义中的存储域;
C251:由 类型定义中的存储域决定,为 data。
4、定义数组变量、指定了与类型定义中不同的存储域
mmm_tsp xdata mmm;
C51/C251:均不会产生告警或错误,并由此处的存储域决定,即 xdata。
可见,在类型定义中指定存储域,一般情况下不会出问题,能够符合预期;
但在一些特殊情况下,可能会超出预期,搞出一些莫名其妙的故障。
在类型定义中指定存储域确实方便应用,
但用户应认识到其中可能存在的风险。
本帖最后由 tzz1983 于 2024-10-26 15:56 编辑
CosyOS 发表于 2024-10-26 14:41
我给你找到了一个示例,
typedef 中指定 存储域,可能出现的一些情况:
好的,挺详细的,感谢分享
我的理解是,对于第二点,可以理解为重复设定域,即便是data, 也会出现错误或警告,这是人为制造二义错误,与编译无关。
第三和第四,层次太深了哈,编译器理解不了{:lol:}, Keil C251 我也有点感觉它 “年久失修”了,不过凑合用还是不错的。
另外,如果层次不这么深,数组还是可以用的。比如实际项目代码:
我一直都这样用,很方便, 定义数组时不用刻意去指定edata,
不管是采用哪种MemModel, 最终栈都是定位在edata.
另外,我支持你的说法,在没有特殊个人偏好的情况下,就好用标准的方法。以避免无畏的错误。
从理论上来说,数据结构体描述的是数据结构本身,它和存储域确实没什么关系的。
tzz1983 发表于 2024-10-26 15:51
好的,挺详细的,感谢分享
我的理解是,对于第二点,可以理解为重复设定域,即便是data, 也会出现错误或警 ...
我们通过类举这些示例,证明在特殊情况下,
类型定义中指定存储域,可能会出现一些问题,
用户自己斟酌。
CosyOS 源码中就有大量的这种深层次定义,
当年在 C51下开发时,一开始就是在类型定义中指定存储域,
出现了各种问题,后来才改为一律在定义变量时指定存储域。
CosyOS 发表于 2024-10-26 14:41
我给你找到了一个示例,
typedef 中指定 存储域,可能出现的一些情况:
另外我也发现了,指针类型确实没有符合原有期望。
比如:
struct
{
/* 成员定义;*/
}xdata BUTTON;
BUTTON* pt;
从主观理解来说,pt是(xdata*)类型,应该是2字节。
而实际上, sizeof(pt) == 4,与预期不符。 C251内核结构体定义区域还有这么多规则啊 tzz1983 发表于 2024-10-26 08:17
没有仔细看代码,不知道为什么产生不可预料的仰错误,可以降低优化等级,关掉全局重入选项试试。
在结构体 ...
感谢大佬解答! 我这就去试试! CosyOS 发表于 2024-10-26 08:42
类型定义时,写 存储域 是无效的,最终结果不会符合你的预期。
存储域是变量的存储域,只有在定义变量时写 ...
感谢大佬解答!我这就去试试
页:
1
[2]