C语言指针-创新互联

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

创新互联公司主要从事成都做网站、成都网站制作、网页设计、企业做网站、公司建网站等业务。立足成都服务郁南,十多年网站建设经验,价格优惠、服务专业,欢迎来电咨询建站服务:028-86922220

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

关于【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  
    
    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  
    
    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  
    
    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  

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  
    
    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语言指针

   **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语言指针

5)对于“例9”

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

    #include "stdafx.h"    
    #include  
    
    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语言指针

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语言指针    

 

 对于*(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语言指针 

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

这个很重要

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

 

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


网页名称:C语言指针-创新互联
URL地址:http://pwwzsj.com/article/pooie.html