为了账号安全,请及时绑定邮箱和手机立即绑定

C语言指针

标签:
C++


https://blog.csdn.net/constantin_/article/details/79575638

就上面的博客作一下笔记:

关于【int (*p)[3]】与【int *p[3]】两个的区别

https://blog.csdn.net/sayesan/article/details/39001609

技巧1:注意*与[与变量结合的优先顺序,p有可能是指针,也有可能是数组,也有可能是函数名。

技巧2:关于“指针类型”的判定:

            1)首先,要确保变量就是一个指针类型。

            2)去掉变量名,剩下的就是指针类型。

技巧3:关于“指针所指向的类型”的判定:

            1)首先,要确保变量就是一个指针类型。

            2)去掉变量名指针的声明符*,剩下的就是指针指向的类型。

void如果来修饰指针运算符*,就代表是任意类型的指针。

int (*p)[3]; 

关于复杂指针类型,上面这个类型。注意(*p)这个括号,仅仅是用来约束运算符优先级的。不要和下面的指针类型混淆。

Int (*p)(int);

上面这个类型。注意(*p)这个括号,代表p指向的是一个函数。

所以在判断(*p)指针的指向的内容类型时,可以将(*p)同时去掉再行判断 。

指针打印:采用%p

1)对于“例二”

     如果ptr指针类型声明为char *,ptr++之后的打印结果为b。

    #include "stdafx.h"    

    #include <stdlib.h> 

    

    int _tmain(int argc, _TCHAR* argv[])

    {

      char a[20]={'a','b','c','d','e','f'};  

        char *ptr= a; //强制类型转换并不会改变a 的类型  

        ptr++; 

         

      printf("%c",*ptr);

      system("pause");

      return 0;

    }

     如果ptr指针类型声明为int *,ptr++之后的打印结果为e。 

    #include "stdafx.h"

    #include <stdlib.h> 

    

    int _tmain(int argc, _TCHAR* argv[])

    {

      char a[20]={'a','b','c','d','e','f'};  

        int *ptr=(int *)a; //强制类型转换并不会改变a 的类型  

        ptr++; 

    

      printf("%c",*ptr);

      system("pause");

      return 0;

    }

      所以当指针声明成不同的类型,++的效果是不一样的。++和指针的类型有关。

      如果指针类型和指针所指向的类型不一致时,要注意++的使用。

     

 2)对于“例三”

    #include "stdafx.h"    

    #include <stdlib.h> 

    

    int _tmain(int argc, _TCHAR* argv[])

    {

       int array[20]={0};  

        int *ptr=array;  

    

    

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

        {  

            (*ptr)++;  

            ptr++;

        }  

    

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

        {  

          printf("[%d] = %d\n",i,array[i]);

        } 

         

      

      system("pause");

      return 0;

    }

3)对于“例四”

#include "stdafx.h"

#include <stdlib.h> 

int _tmain(int argc, _TCHAR* argv[])

{

   

char a[20]="You_are_a_girl";  

int *ptr=(int *)a;  

ptr+=1;

    printf("%d\n",*ptr); 

   system("pause");

   return 0;

}

 对行%d,*ptr输出的是1600483937

 对行%c,*ptr输出的是a

 这是为什么,请高手解答?

4)对于“例五”

    #include "stdafx.h"    

    #include <stdlib.h> 

    

    int _tmain(int argc, _TCHAR* argv[])

    {

          char a[20]="You_are_a_girl";  

            char *p=a;  

            char **ptr=&p;  

            //printf("p=%d\n",p);  

            //printf("ptr=%d\n",ptr);  

            //printf("*ptr=%d\n",*ptr);  

            printf("**ptr=%c\n",**ptr);  

            ptr++;  

            //printf("ptr=%d\n",ptr);  

            //printf("*ptr=%d\n",*ptr);  

            printf("**ptr=%c\n",**ptr); 

      system("pause");

      return 0;

    }

       这个例子有点绕,需要注意,上面我来配个图

        image.png

       **ptr:分解开就是*(*ptr)

                *ptr取指ptr所指向的内容,ptr指向的地址是指针变量p所占用的内存地址,ptr所指向的内容就是指针p变量。

                *(*ptr) 就是*p,也就是取p所指向的a的首地址的值,所以第一次打印ptr的值是Y。

                

                ptr++,就是得明白指针的++与普通的运算符是不一样的(指针变量的++,代表它所指向的个体的内存地址的递增,且增长单位为指针类型所占字节个数)。

                ptr++,也就是 ptr所指向的地址+4(注意是p的地址+4,并非a的地址+4).

                ptr++ ,  就是ptr所指向的内存地址是指针p的内存地址加4个字节的地址,至于这个地址里存储的对象是啥,谁也不知道。

                *ptr,ptr新指向内存地址就是下面的这个蓝牙框。 *(*ptr),就是把*ptr当作是一个指针,而*ptr并非一定是一个指针。这样程序可能就会报错。

        image.png

 

5)对于“例9”

      假如我像下面这么写,会报一个错误:

    #include "stdafx.h"    

    #include <stdlib.h> 

    

    int _tmain(int argc, _TCHAR* argv[])

    {

    int array[10]={0,1,2,3,4,5,6,7,8,9},value;  

    array++;

    value=*array; 

    

        printf("%d\n",value); 

      system("pause");

      return 0;

    }

     error C2105: “++”需要左值

    上面的错误百度了一个解释:https://blog.csdn.net/hou09tian/article/details/75332576

    就是数组名是一个指针,但是不是一个变量。不可能对它进行++运算。++不可使用在常量上

     改一下代码:

    int _tmain(int argc, _TCHAR* argv[])    

    {

    int array[10]={0,1,2,3,4,5,6,7,8,9},value;  

    int *ptr = array;

    ptr++;

    value=*ptr; 

    

        printf("%d\n",value); 

      system("pause");

      return 0;

    }

     结果输出1

    

    其实,说到数组,我还一个 需要补充的:数组元素的内存地址是连续的

    通过下面的代码打印:

 for(int i = 0; i < 10; i++){

    printf("array[%d] address = %d\n",i,&array[i]); 

 }

    image.png

    

6)对于“例十”

     strcpy函数,会将char *指针所指向的字符串复制,而不仅仅是一个字符。

     printf("%s",array);    %s是从起始位置输出字符直到遇到\0为止,所以%s输出char[]数组,会输出整个串。

     

     关于strcpy函数的详解:

     https://blog.csdn.net/okawari_richi/article/details/57411796

7)对于“例十一”  (数组和指针)

     sizeof 函数:https://blog.csdn.net/u012520854/article/details/53511154

     http://blog.sina.com.cn/s/blog_4badbe8e0100qb0s.html (详细说明数组名与指针的关系)

8)对于“例十二”  (结构体和指针)

     https://www.cnblogs.com/winifred-tang94/p/5843440.html

     成员调用的方法(->左边必须是指针,"."左边必须是实体)

   特别注意结构体与数组,和指针的关系是不一样的。

    image.png    

     

     对于*(ptr +1)打印的不是结构体的第2个元素,很奇怪。难道数组名与结构体名不一样?

         printf("%s\n","----------结构体名取结构体正常数据------------------"); 

      printf("%d\n",*ss); 

      printf("%d\n",*(ss+1));

      

      增加上述代码,工程一编译就报错:

      

                错误1error C2100: 非法的间接寻址

                错误2error C2676: 二进制“+”: “wmain::MyStruct”不定义该运算符或到预定义运算符可接收的类型的转换

      

       所以我得出一个结论,数组名与结构体名有完全不一样的特性:结构体名不能当成指针使用,结构体名不是指针常量。

        

        注意这行代码:

    struct MyStruct *ptr=&ss;

        假如ss是数组,上面的代码就不用加&号了。

    struct MyStruct *ptr=ss;

        但是结构体会报错:

                错误1error C2440: “初始化”: 无法从“wmain::MyStruct”转换为“wmain::MyStruct *”

        这就更加证明了结构体名不是指针常量这个结论 。

        

       继续修改代码:

       image.png 

        

        

        注意上面的打印结果,通过pstr取的结构体元素地址是正确的,但是ptr取的结构体元素地址是错误的。

        注意代码中ptr与pstr的定义:

        

      struct MyStruct *ptr=&ss;  

      int *pstr=(int*)&ss;

        ptr指向的类型是 MyStruct,指向的对象为结构体实体ss。

        pstr指向的类型是int,指向的对象为结构体的实体ss的首元素。

        ptr+1,就是&ss这个地址+sizeof(MyStruct),就是&ss+16。

        pstr+1,就是&ss这个地址+sizeof(int),就是&ss+4。

        

      --------------------------------------------------------------------------------------------   

      |   结构体与数组的共性:

      |        1)结构体实体的地址和结构体第一个元素的地址一样, 各元素的地址也是连续的。(特殊情况也有不连续的)

      |             数组实体的地址和数组第一个元素的地址一样, 各元素的地址也是连续的。

      |        2)数组和结构体自身的实体(变量)并不占据独立的内存(和首元素地址一样),只有元素才占用真正的内存地址,

      |             它只是标明自身的元素是一组特殊的数据结构, 通过实体封装,便于元素的访问。

       |   

      |  结构体与数组的区别:

      |       1)数组名是指针常量,但是结构体名和指针没有任何的关系。

     --------------------------------------------------------------------------------------------      

        

9)对于“例十三”        

       注意作者对结构体的特殊之处的解释

        

10)指针类型的转换

       可以把指针的值当作一个整数取出来,也可以把一个整数值当作地址赋给一个指针

        

11) 指针安全问题

       这个很重要

      使用指针必须要清楚指针指向了哪里

     

     

 

©著作权归作者所有:来自51CTO博客作者屠夫章哥的原创作品,如需转载,请注明出处,否则将追究法律责任


点击查看更多内容
2人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消