嵌入式系统C语言编程的心得体会

来源:互联网 发布:淘宝助理增量下载订单 编辑:程序博客网 时间:2024/05/01 22:13
最近经常在解释程序中指针的应用手法,发现多数人对指针的认识并不完整,捉住了指针的表面现象却没有很好的理解指针的本质特性。上次写指针编的时候也没有很好的解释指针的本质特性,以及这个特性在C语言中的应用方法。
    今天就把这些天的体会总结一下,从三个方面来说明这个问题,一是指针相关的名称以其含义,二是指针在C语言编译时的编译器的工作原理,三是应用时的使用注意事项和优缺点。
    在这里我以8位系统(AVR单片)来解释,其他系统以此类推,主要针对GNU的GCC编译器来说明。首先说一下定义我们定义uint8是8位无符号型变量,因此定义: uint8 v 这里v就是一个无符号的8位变量;uint8 *p 这里p就是一个指针型变量,这个指针型变量是一个指向8位无符号型变量的指针。在AVR中地址位数是16位的,因此,这个指针变量是个16位的数据。编译时在内存中将分配一个8位的空间给变量v,假设分配给v的内存地址是0x000A;分配两个8位空间给变量p,因为p是个指针型的变量,存放的是16位的地址数据,假设分配p的内存地址是0x00010-0x0011。
    考查以下代码
    uint8 v;执行这个语句仅是分配了一个内存空间给v,v是什么值并不确定;
    uint8 *p;执行这个语句分配了一个内存空间给p,p的值也是不确定的;
    v = 0;  执行这个语句的时候对v变量赋值也就是对0x000A空间赋值0;
    *p = 0; 我们看看这时汇编语句是什么LDD     R30,Y+1  
                                    LDD     R31,Y+2   
                                    STD     Z+0,R1    注:在AVR中Z寄存器有R30和R31构成
            从这里我们看到,实际上就是把R1的值付给了Y寄存器里存放的地址空间,而Y的值并没有赋值,而且延续前一次赋值的状态,这个就造成了*p=0赋值位置的不确定性。在程序运行的过程中就会出现致命的问题,可能会造成系统死机。从这个例子也可以看出,简单的把*p看作是一个变量,而采用一般变量的使用方法来处理它是不妥当的,这是有前提的。
    p = &v;我们看这个汇编 MOVW    R24,R28     
                         ADIW    R24,0x03 
                         STD     Y+2,R25   
                         STD     Y+1,R24   注:对Y赋值

    *p = 0;在看这个汇编   LDD     R30,Y+1   
                         LDD     R31,Y+2    
                         STD     Z+0,R1   
    从这里我们可以发现,只有定义一个变量,并且将这个变量的地址赋值给指针变量后,*p才可以采用一般变量的处理方法对其进行操作。
    很多时候发现是使用指针后系统会死机或数据并非我们预想的,主要问题就出在这。在使用操作系统传递消息或邮箱时,这种情况特别明显。看是和说明的操做相同,却为什么不能正常工作呢。因为你忽略对指针变量的赋值,而直接使用*p来作为变量处理。
    这个解释比较绕口,要实际操作中慢慢体会,但要捉住一点,指针就是地址,指针变量就是一个存放地址的空间。但出现问题或思路混乱的时候,将地址空间画出来,并按照你的程序编写的步骤推算一下。
原创粉丝点击