zyqcome 发表于 2018-2-13 12:11:54

分享:c51指针函数数组取长度-sizeof

想把代码写的更可配置一些,尝试指针函数,在用 sizeof 的时候遇到些问题贴出来给大家分享

* 示例函数
void dosomething(void) {
        static int i=0;
        i=i+1;
}

* 示例指针函数数组
void (*p_array[])(void) = {
                                                                                                                dosomething,
                                                                                                                dosomething,
                                                                                                                dosomething,
                                                                                                                dosomething,
                                                                                                                dosomething,
                                                                                                                dosomething,
                                                                                                                dosomething,
                                                                                                                dosomething,
                                                                                                                dosomething,
                                                                                                                dosomething,
                                                                                                        };


*出错的调用函数
int main(void)
{
        for(array_size = 0;array_size < sizeof(p_array)/sizeof(int);array_size++)        {
                (*p_array)();
        }
        while(1);
}

*跑通的用法
int main(void)
{
        for(array_size = 0;array_size < sizeof(p_array)/sizeof(p_array);array_size++)        {
                (*p_array)();
        }
        while(1);
}

错误分析,我想当然的以为 void (*p_array[])(void) 每个元素的长度是两位。结果跑飞了
正确的在这里:
stmt levelsource
   1      int *p1;         /* generic ptr (3 bytes) */
   2      int xdata *p2;   /* xdata ptr (2 bytes) */
   3      int idata *p3;   /* idata ptr (1 byte) */
   4      int code *p4;      /* code ptr (2 bytes */
   5
   6      void pconvert (void) {
   7   1    p1 = p2;         /* xdata* to generic* */
   8   1    p1 = p3;         /* idata* to generic* */
   9   1    p1 = p4;         /* code*to generic* */
10   1
11   1    p4 = p1;         /* generic* to code* */
12   1    p3 = p1;         /* generic* to idata* */
13   1    p2 = p1;         /* generic* to xdata* */
14   1
15   1    p2 = p3;         /* idata* to xdata* (WARN) */
*** WARNING 259 IN LINE 15 OF P.C: pointer: different mspace
16   1    p3 = p4;         /* code*to idata* (WARN) */
*** WARNING 259 IN LINE 16 OF P.C: pointer: different mspace
17   1    }

ASSEMBLY LISTING OF GENERATED OBJECT CODE
      ; FUNCTION pconvert (BEGIN)
                      ; SOURCE LINE # 7
0000 750001 R   MOVp1,#01H
0003 850000 R   MOVp1+01H,p2
0006 850000 R   MOVp1+02H,p2+01H
                      ; SOURCE LINE # 8
0009 750000 R   MOVp1,#00H
000C 750000 R   MOVp1+01H,#00H
000F 850000 R   MOVp1+02H,p3
                      ; SOURCE LINE # 9
0012 7B05       MOVR3,#0FFH
0014 AA00   R   MOVR2,p4
0016 A900   R   MOVR1,p4+01H
0018 8B00   R   MOVp1,R3
001A 8A00   R   MOVp1+01H,R2
001C 8900   R   MOVp1+02H,R1
                      ; SOURCE LINE # 11
001E AE02       MOVR6,AR2
0020 AF01       MOVR7,AR1
0022 8E00   R   MOVp4,R6
0024 8F00   R   MOVp4+01H,R7
                      ; SOURCE LINE # 12
0026 AF01       MOVR7,AR1
0028 8F00   R   MOVp3,R7
                      ; SOURCE LINE # 13
002A AE02       MOVR6,AR2
002C 8E00   R   MOVp2,R6
002E 8F00   R   MOVp2+01H,R7
                      ; SOURCE LINE # 15
0030 750000 R   MOVp2,#00H
0033 8F00   R   MOVp2+01H,R7
                      ; SOURCE LINE # 16
0035 850000 R   MOVp3,p4+01H
                      ; SOURCE LINE # 17
0038 22         RET
      ; FUNCTION pconvert (END)

参考链接:http://www.keil.com/support/man/docs/c51/c51_le_ptrconversions.htm

另外还在软件仿真的时候,遇到 *** error 65: access violation at : no 'execute/read' permission
参考:http://blog.csdn.net/bobbat/article/details/41059721 的2条
2.仿真出现*** error 65: access violation at 0x0000000C : no 'read' permission的错误是因为没有相应的内存映射,可能的原因是由于软件仿真没有分配相应的映射地址。如果想要避开这个错误,可以再keil软件的仿真状态下面点击菜单栏的Debug-》Memory Map,如下图添加缺少的内存映射值范围,如0x0000000c在0x00000000-0x0000000f之间。如下图:

然后点击Map Range,最后close即可。在Run就没有错误了。

all;

su33691 发表于 2018-2-13 12:24:43

51的RAM空间碎片化,在51上用指针一不小心就容易出错。

lxa0 发表于 2018-2-13 19:11:52

谢谢楼主 的好资料~~~~~~~~~~
页: [1]
查看完整版本: 分享:c51指针函数数组取长度-sizeof