programshao 发表于 2024-2-23 17:41:00

STC15程序移植到STC32时发现,Keil中指针变量做函数参数,C51和C251 编译有区别!

问题不太容易描述,直接看代码:

typedef unsigned char        uint8;
typedef unsigned int        uint16;

uint8 xdata buf_xdata _at_ 0x0200;

void test(uint8 *pt)
{
        uint8 i;
        for(i = 0; i < 3; i++) *pt++ = i;
}

void main()
{
        uint8 xdata *pt;//指向xdata区
        uint16 addr;

        test((uint8 xdata *)0x0200);        //此行可得正常结果 buf_xdata = 0x00; buf_xdata = 0x01; buf_xdata = 0x02;
       
        pt = 0x0203;
        test(pt);                                        //此行可得正常结果 buf_xdata = 0x00; buf_xdata = 0x01; buf_xdata = 0x02;
       
        addr = 0x0206;
        test((uint8 xdata *)addr);                //此行在STC32系列单片机C251中编译得不到预期结果!但在STC15系列单片机C51中编译可正确执行
                                                        //预期结果:buf_xdata = 0x00; buf_xdata = 0x01; buf_xdata = 0x02;
        while(1);
}

test()函数的参数是指针

(uint8 xdata *)0x0200 -----地址0x0200(常量)强制转化为指向xdata区的指针,正常

pt = 0x0203;-----指向xdata区的指针pt赋值0x0203,正常

addr = 0x0206;-----变量赋值0x0206,然后强制转化为指向xdata区的指针,C51正常,C251就不正常

想不明白,哪位大神能给指点一二,谢谢

飞捷 发表于 2024-2-24 09:53:56

我试过用C51移值,发现函数的参数,不能用公式直接代入,需要在外现处理好,例如
uint8 xdata *pt;//指向xdata区   
pt = 0x0203;
test(pt);   

但是如果你直接
addr = 0x0206;
test((uint8 xdata *)addr);
就会报错。

还有addr = 0x0206;
test((uint8 xdata *)addr);   这个还有个问题,一般先定义addr为指针,然后再给addr赋值,   但是你这个是先给ADDR定义一个16位(有可能得定义32位),然后再强制转化。

gentleman 发表于 2024-2-24 10:28:25

本帖最后由 gentleman 于 2024-2-24 10:32 编辑

测试了一下
测试环境 屠龙刀-STC32G12K128
打印数组没发现问题
检查其他方面吧





angmall 发表于 2024-2-24 10:34:41

addr = 0x0206;-----变量赋值0x0206,然后强制转化为指向xdata区的指针,C51正常,C251就不正常
因为这么操作,他的地址就不是在xdata了,是在edata了。



https://www.stcaimcu.com/data/attachment/forum/202311/01/072845tvf0kplhvf7vcyzl.jpg




tzz1983 发表于 2024-2-24 11:24:41

我个人的理解:
addr是16位,通用指针是32位,强制转换时,自动高位补0导至指针指向了edata区. C51不会有这种事情。
强制转换有时候是不安全的转换,比如32位转16位,编绎器只是按照默认规则转换数据,不能保证转换结果一定正确.
编辑代码时尽量考虑可以多种环境运行。
尝试一下改成这样:
test((uint8 xdata *)0+addr);

test(&((uint8 xdata *)0));



programshao 发表于 2024-2-24 18:33:06

飞捷 发表于 2024-2-24 09:53
我试过用C51移值,发现函数的参数,不能用公式直接代入,需要在外现处理好,例如
uint8 xdata *pt;//指向xd ...

addr定义为32位也不行

programshao 发表于 2024-2-24 18:39:19

本帖最后由 programshao 于 2024-2-24 18:46 编辑

tzz1983 发表于 2024-2-24 11:24
我个人的理解:
addr是16位,通用指针是32位,强制转换时,自动高位补0导至指针指向了edata区. C51不会有 ...
大佬提供的方法是可行的。

我不理解的是:
常量0x0200(或者0)在经过(uint8 xdata *)的强制转换时,会将高位补上0x01,即0x010206,从而指向xdata区;
但是变量addr=0x0206在经过(uint8 xdata *)的强制转换时,却会将高位补成0,就指向了edata区了
为何会有这种差异?

programshao 发表于 2024-2-24 18:55:31

gentleman 发表于 2024-2-24 10:28
测试了一下
测试环境 屠龙刀-STC32G12K128
打印数组没发现问题


能不能发我完整的工程文件看看?我怀疑是不是跟编译条件有关?

gentleman 发表于 2024-2-25 08:18:02

编译环境
xSmall -large

工程见附件







飞捷 发表于 2024-2-26 00:26:41

programshao 发表于 2024-2-24 18:33
addr定义为32位也不行

最后找出原因了吗?
页: [1] 2
查看完整版本: STC15程序移植到STC32时发现,Keil中指针变量做函数参数,C51和C251 编译有区别!