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

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


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

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

https://blog.csdn.net/ywb201314/article/details/52062059


技巧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;
    }

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

        C语言指针_C 指针

       **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并非一定是一个指针。这样程序可能就会报错。



        C语言指针_C 指针_02

 

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]); 
 }

    C语言指针_C 指针_03

    

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

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



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

    C语言指针_C 指针_04    

     

     对于*(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 *”

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

        



       继续修改代码:

       C语言指针_C语言_05 

        

        

        注意上面的打印结果,通过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) 指针安全问题

       这个很重要

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