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) 指針安全問題

       這個很重要

      使用指針必須要清楚指針指向了哪裏



     

     


 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章