初识c指针

//
   初学C指针  19th . Oct . 2011  EVE
/

零、不得不说。

    此博文仅代表个人观点,如有悖“天理”,欢迎指正。
             ----
    欢迎所有的想一起研究的朋友加我,嗯,人多力量大嘛!

    下面进入正题~

本文引用:

http://topic.csdn.net/u/20070112/09/35186e5a-0d94-4ea6-9b72-c5463cb3d1f3.html   [深入理解c指针]
    ----------------------------------

一、什么是指针?
    
    大家都知道,计算机也是靠物理原理实现的,

    所以,物理操作就一定要有操作的对象,

    那么CPU直接操作的对象是什么呢?

    是所谓的“内存条”

    这个内存条上都是有地址编号的,就像我们住的小区,

    每一家都有每一家的地址,计算机在传送数据的时候

          (就像我们要给朋友家送点东西,就一定要知道他家的地址一样)

    需要地址来识别这个信息
    
          (哪家哪户,别搞错了,我去一个朋友家送吃的,结果错进了一个美女家,

           碰巧我又长的很帅,而她的情人就在这个时候回来了,麻烦了)

    那么指针就是:比如说我,我自己家有个地址,然后,我知道我同学家的地址

     我就能从我家,去我同学家,这不废话么,

    换个说法就是:int *p ;         //定义了一个整形指针变量
        
          int a;           //声明一个整形变量,再简单不过了,

          p = &a ;         //取了同学a的地址,告诉了我,我是p

                           //  —— ,——  对,我是p

     那么指针的指针就是:我知道我同学家的地址,而我的同学又碰巧知道另一个


     我想知道的女孩家的地址,他能帮我找到她。  


    也就是:    int **p ;          //我是p(二级指针...)

                int *pa ;          //我朋友(一级指针)
        
        int a ;            //The girl

        pa = &a ;          //朋友知道女孩家的地址

        p = &pa ;          //我知道朋友家的地址

        printf ("%x",*p);     //我去了朋友家(取出p中存的a的地址)

        printf ("%x",**p);     //朋友告诉了我她家的地址(取出a)

二、认识指针

    在认识指针之前,需要通过几个方面:

         1.什么是指针的类型?

     从语法的角度看,你只要把指针声明语句里的指针名字去掉,

     剩下的部分就是这个指针的类型。这是指针本身所具有的类型。

       (1)int*ptr;//指针的类型是int*  

       (2)char*ptr;//指针的类型是char*  

       (3)int**ptr;//指针的类型是int**  

       (4)int(*ptr)[3];//指针的类型是int(*)[3]  

       (5)int*(*ptr)[4];//指针的类型是int*(*)[4]

     是不是很容易?

     2.什么是指针指向的类型?

         当你通过指针来访问指针所指向的内存区时,指针所指向的类型决定了

          编译器将把那片内存区里的内容当做什么来看待。  

         从语法上看,你只须把

         指针声明语句中的指针名字和名字左边的指针声明符*去掉,

         剩下的就是指针所指向的类型。

       (1)int*ptr;//指针所指向的类型是int  

       (2)char*ptr;//指针所指向的的类型是char  

       (3)int**ptr;//指针所指向的的类型是int*  

       (4)int(*ptr)[3];//指针所指向的的类型是int()[3]  

       (5)int*(*ptr)[4];//指针所指向的的类型是int*()[4]   

     3.指针的值(或者叫指针指向的内存区)?

         指针的值是指针本身存储的数值,
    
         这个值将被编译器当作一个地址,而不是一个一般的数值。

         在32位程序里,所有类型的指针的值都是一个32位整数,
    
         因为32位程序里内存地址全都是32位长。  
    
         指针所指向的内存区就是从指针的值所代表的那个内存地址开始,
    
         长度为sizeof(指针所指向的类型)的一片内存区。
    
           以后,我们说一个指针的值是XX,
    
         就相当于说该指针指向了以XX为首地址的一片内存区域;
    
         我们说一个指针指向了某块内存区域,
    
         就相当于说该指针的值是这块内存区域的首地址。

     以后,每遇到一个指针,都应该问问:
    
     这个指针的类型是什么?指针指的类型是什么?该指针指向了哪里?   

     我们可以用一个指针和一个循环来遍历一个数组,看例子:
    -------------------
         intarray[20];  

         int*ptr=array;  

         ...  

         //此处略去为整型数组赋值的代码。  

               ...  
         
         for(i=0;i <20;i++)  

         {  
         
        (*ptr)++;  

        ptr++;  
       
         }

     这个例子将整型数组中各个单元的值加1。由于每次循环都将指针ptr加1,

     所以每次循环都能访问数组的下一个单元。   

     再看例子:
      -------------------
       char a[20];  

       int  *ptr=a;  

       ...  
       ...  
    
       ptr+=5;
    
         在这个例子中,ptr被加上了5,编译器是这样处理的:
    
         将指针ptr的值加上5乘sizeof(int),
    
         在32位程序中就是加上了5乘4=20。
    
         由于地址的单位是字节,故现在的ptr所指向的地址比起加5后的
    
         ptr所指向的地址来说,向高地址方向移动了20个字节。
    
         在这个例子中,没加5前的ptr指向数组a的第0号单元开始的四个字节,
    
         加5后,ptr已经指向了数组a的合法范围之外了。
    
         虽然这种情况在应用上会出问题,但在语法上却是可以的。
    
         这也体现出了指针的灵活性。   

         如果上例中,ptr是被减去5,那么处理过程大同小异,
    
         只不过ptr的值是被减去5乘sizeof(int),
    
         新的ptr指向的地址将比原来的ptr所指向的地址
    
            向低地址方向移动了20个字节

     4.指针本身占据的地址(内存)

         指针本身占了多大的内存?你只要用函数
    
         sizeof(指针的类型)测一下就知道了。在32位平台里,指针本身占据了4个字节的长度。   

三、指针表达式

    啥是指针表达式啊?

            简单的说就是左边右边都是指针。

    比如:
    -----------------   
         int *p ;
    
     float f ;

     p = (float *)&f ;  //这是一个指针表达式
    
     int a,b;

     int array[10];

     int *pa;

     pa = &a //这是一个指针表达式

     int **ptr = &pa ;//this too

     *ptr = &b ; //and this

     pa = arry; //this

     pa ++;    //this

   犹豫指针表达式的结果是一个指针,所以指针表达式也具有指针的四个要素!

   这里有一点需要注意的就是说,指针表达式左边与右边的指针的类型必须相同

   当然了,不相同,有的编译器也不会报错,
   
   C给人们的自由,更高的自由就意味着永远的警惕!

   有的同学问了说:不相同能怎么样呢?

   问题大了!接着看,


四、指针的算数运算
    ---------------
       char  a[20];  

      int   *ptr=a;  
      ...  
       ...  

      ptr++;

    在上例中,指针ptr的类型是int*,它指向的类型是int,
    
    它被初始化为指向整形变量a。接下来的第3句中,指针ptr被加了1,
    
    编译器是这样处理的:它把指针ptr的值加上了sizeof(int),
    
    在32位程序中,是被加上了4。由于地址是用字节做单位的,
    
    故ptr所指向的地址由原来的变量a的地址向高地址方向增加了4个字节。  

    由于char类型的长度是一个字节,
    
    所以,原来ptr是指向数组a的第0号单元开始的四个字节,
     ----------------------------------------------
    此时指向了数组a中从第4号单元开始的四个字节。
     ---------------------------------------
    c语言的数组不做过界检查!
  -------------------
        char  *str[3]={  

          "Hello,thisisasample! ",

          "Hi,goodmorning. ",  

          "Helloworld "  

        };

        chars[80];  

        strcpy(s,str[0]);//也可写成strcpy(s,*str);  

        strcpy(s,str[1]);//也可写成strcpy(s,*(str+1));  

        strcpy(s,str[2]);//也可写成strcpy(s,*(str+2));
    
    上例中,str是一个三单元的数组,该数组的每个单元都是一个指针,
    
        这些指针各指向一个字符串。把指针数组名str当作一个指针的话,
    
        它指向数组的第0号单元,它的类型是char**,它指向的类型是char*。

        *str也是一个指针,它的类型是char*,它所指向的类型是char,
    
        它指向的地址是字符串 "Hello,thisisasample! "的第一个字符的地址,
    
        即 'H '的地址。   str+1也是一个指针,
    
        它指向数组的第1号单元,它的类型是char**,它指向的类型是char*。
    ------------
        chars= 'a ';

        int*ptr;  

        ptr=(int*)&s;

        *ptr=1298;  

    指针ptr是一个int*类型的指针,它指向的类型是int。
    
        它指向的地址就是s的首地址。在32位程序中,s占一个字节,int类型占四个字节。
    
        最后一条语句不但改变了s所占的一个字节,
    
        还把和s相临的高地址方向的三个字节也改变了。这三个字节是干什么的?
    
        只有编译程序知道,而写程序的人是不太可能知道的。
    
        也许这三个字节里存储了非常重要的数据,
    
        也许这三个字节里正好是程序的一条代码,而由于你对指针的马虎应用,
    
        这三个字节的值被改变了!这会造成崩溃性的错误!!!!!!!!!  

        在指针的强制类型转换:ptr1=(TYPE*)ptr2中,
    
        如果sizeof(ptr2的类型)大于sizeof(ptr1的类型),
    
        那么在使用指针 ptr1来访问ptr2所指向的存储区时是安全的。
    
        如果sizeof(ptr2的类型)小于sizeof(ptr1的类型),
    
        那么在使用指针ptr1来访问ptr2所指向的存储区时是不安全的。

        至于为什么,读者结合上例,想想应该会明白的。

五、野指针

    什么是野指针?

    就是,这个指针是很野,它不老实,它会乱成一气!

    没准指向的是没有内容的地址,好呀,好呀,没事呀,没事呀。

    过了一会,它偷偷的指向了系统内存!!! 完了,系统让它弄屎了!!!!

    使用指针一定要注意:
       
        1.定义出来的指针首先赋为空。

        2.使用完毕之后的指针,我是指free();了之后的,也要赋为空。

        3.使用的指针不要操作超越了变量的作用范围

    愿君细心啊!

六、其他

    C语言的精髓就是指针了,

    最难学的也是指针,

    但是它是C的灵魂所在。               好好学把。:-)

    数组名存放的是数组的首地址,也就是指针,但是它是指针常量。

    什么是常量,5是常量,2是常量,1是常量,999也是常量。

    就是不能改变的,不能让他自加自减,系统会很不高兴的。

    int array [10];

    t = sizeof (array);

    在表达式sizeof(array)中,数组名array代表数组本身,
    
    故这时sizeof函数测出的是整个数组的大小。

好了,就这么多,欢迎多多提提意见,我是个知错就改的银。

欢迎转载,请注明出处。                 CSDN ID :Coder_Black

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值