csmjmcc 发表于 2014-4-22 15:54:34

KEIL C51 库函数 疑问

在此发出疑问,有两个作用:
1、帮助本人解答问题。
2、也给菜鸟们提个醒,别走弯路。
问题是:
        错误代码如下:

        char *head, *tail;
       
        head = strstr(dat_ptr, "{TER,G1,");
        if(head == 0) return FALSE;            //这里总是返回 实际dat_ptr中数据是有涵盖“{TER,G1,”的

        正确代码如下:

        char *head, *tail;
       
        head = strstr(dat_ptr, "{TER,G1,");
        if(head == NULL) return FALSE;      //库函数中定义 #define NULL ((void *) 0L)

请各位老师帮助解答 上两则代码中注释的两栏有什么区别?

mail2li 发表于 2014-4-23 10:59:16

#define NULL ((void *)0)
你的问题有两个
1. 先搞清楚NULL空指针的含义 已经他和0的关系
2. C51对指针有一些特别的定义 我记得是根据类型会有一些特别的标记 具体你可以看看C51的自带的文档

csmjmcc 发表于 2014-4-23 15:09:51

谢谢回复!
1、先前,在ARMCC及GCC 同是如此:if(head == 0) return FALSE; 没啥问题。 于是乎,直接搬移到C51,结果程序跟踪发现在C51中出问题了。
2、试图探个究竟,查看编译代码,因难以读懂,故而弃之。将NULL与当前的指针值打印出来,结果如下: NULL为 i:0000 head为 x:0000.这两项结果表示啥意思,搞不懂!
3、或许不同系统NULL有不同的值,但我们仅从C51系统下看问题,NULL 指向是否为0?

sgj245609615 发表于 2014-4-23 15:57:35

学习下               

csmjmcc 发表于 2014-4-24 09:18:51

本帖最后由 csmjmcc 于 2014-4-24 10:01 编辑

探究一番,陈述如下,以求看官批评指正:
1、我们知道,C51函数返回一般指针时,为R3,R2,R1.其中R3-存放的是存储类型值。存储类型值有DATA/IDATA=0X00、XDATA=0X01...(其他不在此赘述)。

2、且看编译代码:
385: static bit rec_deal(const Uchar *dat_ptr)
   386: {
   387:         intlen;
   388:         char *head, *tail;
   389:         
   390:         head = strstr(dat_ptr, "{TER,G1,");
C:0x038A    7543FF   MOV      0x43,#0xFF
C:0x038D    75440E   MOV      0x44,#0x0E
C:0x0390    75454A   MOV      0x45,#0x4A
C:0x0393    1208DF   LCALL    strstr(C:08DF)
C:0x0396    8B3A   MOV      0x3A,R3
C:0x0398    8A3B   MOV      0x3B,R2
C:0x039A    893C   MOV      0x3C,R1
   391:         if(head == NULL) return FALSE;
   392:
C:0x039C    E9       MOV      A,R1       //这里R3,R2,R1均参与运算,查看返回是否为0.      
C:0x039D    4A       ORL      A,R2
C:0x039E    4B       ORL      A,R3
C:0x039F    7002   JNZ      C:03A3
C:0x03A1    C3       CLR      C
C:0x03A2    22       RET      

385: static bit rec_deal(const Uchar *dat_ptr)
   386: {
   387:         intlen;
   388:         char *head, *tail;
   389:         
   390:         head = strstr(dat_ptr, "{TER,G1,");
C:0x038A    7543FF   MOV      0x43,#0xFF
C:0x038D    75440E   MOV      0x44,#0x0E
C:0x0390    75454D   MOV      0x45,#0x4D
C:0x0393    1208E2   LCALL    strstr(C:08E2)
C:0x0396    8B3A   MOV      0x3A,R3
C:0x0398    8A3B   MOV      0x3B,R2
C:0x039A    893C   MOV      0x3C,R1
   391:         if(head == 0) return FALSE;
   392:
C:0x039C    AE02   MOV      R6,0x02//0x02亦即0区 R2
C:0x039E    AF01   MOV      R7,0x01//0x01亦即0区 R1      而在这里仅 R2 R1参与运算 查看返回是否为0.
C:0x03A0    EF       MOV      A,R7
C:0x03A1    4E       ORL      A,R6
C:0x03A2    7002   JNZ      C:03A6
C:0x03A4    C3       CLR      C
C:0x03A5    22       RET      

3、结论:当 if(head == 0) 时,R3-存储类型将忽略它,本语句视为存储类型为data/idata.
            当if(head == NULL)时,R3-存储类型不可忽略,因NULL已明确定义为void*型。
            故 if(head == 0)与 if(head == NULL)两语句在C51中是不同的含义,不可轻视之。

4、留下的疑虑: ARMCC是否亦隐藏如此问题??

鸣谢各位导师指导,指正!

csmjmcc 发表于 2014-4-24 09:26:41

本帖最后由 csmjmcc 于 2014-4-24 10:03 编辑

csmjmcc 发表于 2014-4-23 15:09
谢谢回复!
1、先前,在ARMCC及GCC 同是如此:if(head == 0) return FALSE; 没啥问题。 于是乎,直接搬移 ...

这里补充:
          打印用 printf("HEAD: %p", head); 语句
       现在明白打印的结果:X:0000 -----指的是 在XDATA区 指针值为 0000.i:0000 ------指的是 在 DATA/IDATA区 指针值为 0000.
页: [1]
查看完整版本: KEIL C51 库函数 疑问