C語言指針的初始化和賦值

1、指針的初始化

 

指針初始化時,“=”的右操作數必須爲內存中數據的地址,不能夠是變量,也不能夠直接用整型地址值(可是int*p=0;除外,該語句表示指針爲空)。此時,*p僅僅是表示定義的是個指針變量,並沒有間接取值的意思。

比如:

int a = 25;

int *ptr = &a;

int b[10];

int *point = b;   

int *p = &b[0];

 

假設:int  *p;

    *p = 7;

則編譯器(vs2008)會提示The variable 'p' is being used without being initialized.即使用了未初始化的變量p。

由於p是指向7所在的地址,*p = 7給p所指向的內存賦值,p沒有賦值,所以p所指向的內存位置是隨機的,沒有初始化的。

int k;

int *p;

p = &k;  //給p賦值

*p = 7; //給p所指向的內存賦值,即k= 7

 

2、指針的賦值

int *p;

int a;

int b[1];

p = &a; 

p = b; 

指針的賦值,“=”的左操作數能夠是*p,也能夠是p。

當“=”的左操作數是*p時,改變的是p所指向的地址存放的數據;

當“=”的左操作數是p時,改變的是p所指向的地址。

數組的變量名b表示該數組的首地址,因此p=b;也是正確的

 

同類型的指針賦值:

 

int val1 = 18,val2 = 19;

int *p1,*p2;

p1 = &val1;

p2 = &val2;

p1 = p2;   //注意啦,p1指向了val2,而沒有指向val1

 

備註:字符串與指針的初始化和賦值

初始化:

char *cp = "abcdefg"; //這個初始化過程,是將指針cp指向字符串的首地址,而並非傳遞字符串的值。由於,在C語言裏面,沒有總體處理一個字符串的機制

賦值:

cp = "abcdefg";

*cp=”abcdefg” ;//錯誤!字符串常量傳遞的是它的首地址,不能夠通過*cp改動該字符串的值,由於該字符串爲常量,而它僅僅是簡單的將指針指向該字符串常量

 

3、指針常量

 

在C語言中沒有一種內建(built-in)的方法去表示指針常量,所以當我們使用它的時候通常先寫成整型常量的形式,然後再通過強制類型轉換把它轉換成對應的類型,如:int * , double * , char *等。 所以後面所看到的的做法是不行的: int *p = 0x12345678 ; 正確的方式應爲:int *p = (int *) 0x12345678; 要注意指針中僅僅能存放地址,不能將一個非0值整型常量表達式或者其它非地址類型的數據賦給一個指針,原因就在此。在大多數計算機中,內存地址確實是以無符號整型數來表示的,並且多以16進製表示,但我們在C語言中不能用整型數去表示地址,僅僅能用指針常量來表示,由於它是被用來賦給一個指針的。

對於這個賦值問題還能夠換一個角度去理解,在C語言中,使用賦值操作符時,賦值操作符左邊和右邊的表達式類型應該是同樣的,假設不是,賦值操作符將試圖把右邊表達式的值轉換爲左邊的類型。所以假設寫出int *p = 0x12345678 ; 這條語句編譯器會報錯:'=' : cannot convert from ' const int ' to ' int * ' ,由於賦值操作符左邊和右邊的表達式的類型應該同樣,而0x12345678是int型常量,p是一個指向int型的指針,兩者類型不同,所以正確的方式是:int *p = (int *) 0x12345678 ; 

 

4、指針初始化補充

 

ANSI C定義了零指針常量的概念:一個具有0值的整形常量表達式,或者此類表達式被強制轉換爲void *類型,則稱爲空指針常量,它能夠用來初始化或賦給不論什麼類型的指針。也就是說,我們能夠將0、0L、'/0'、2–2、0*5以及(void *)0賦給一個不論什麼類型的指針,此後這個指針就成爲一個空指針,由系統保證空指針不指向不論什麼對象或函數。

ANSI C還定義了一個宏NULL,用來表示空指針常量。大多數C語言的實現中NULL是採用後面這樣的方式定義的:#define  NULL  ((void *)0)。

對指針進行初始化時經常使用的有下面幾種方式:

  1.採用NULL或空指針常量,如:int *p = NULL;或 char *p = 2-2; 或float *p = 0;

  2.取一個對象的地址然後賦給一個指針,如:int i = 3;  int *ip = &i;

  3.將一個指針常量賦給一個指針,如:long *p = (long *)0xfffffff0;

  4.將一個T類型數組的名字賦給一個同樣類型的指針,如:char ary[100]; char *cp = ary;

  5.將一個指針的地址賦給一個指針,如:int i = 3;  int *ip = &i;int **pp = &ip;

  6.將一個字符串常量賦給一個字符指針,如:char *cp = “abcdefg”;

對指針進行初始化或賦值的實質是將地址或同類型(或相兼容的類型)的指針賦給它,而無論這個地址是怎麼取得的。要注意的是:對於一個不確定要指向何種類型的指針,在定義它之後最好把它初始化爲NULL,並在解引用這個指針時對它進行檢驗,防止解引用空指針。另外,爲程序中不論什麼新創建的變量提供一個合法的初始值是一個好習慣,它能夠幫你避免一些不必要的麻煩。

 

5、void *型指針

 

ANSI C定義了一種void *型指針,表示定義一個指針,但不指定它指向何種類型的數據。void *型指針作爲一種通用的指針,能夠和其他不論什麼類型的指針(函數指針除外)相互轉化而不須要類型強制轉換,但不能對它進行解引用及下標操作。C語言中的malloc函數的返回值就是一個void *型指針,我們能夠把它直接賦給一個其他類型的指針,但從安全的編程風格角度以及兼容性上講,不妨將返回的指針強制轉換爲所需的類型,另外,malloc在無法滿足請求時會通過返回一個空指針來作爲“內存分配失敗”的信號,所以要注意返回值指針的判空

 

6、指向指針的指針

 

在指針初始化的第5種方式中提到了用一個指針的地址來初始化一個指針。回顧一下上一講的內容:指針是一種變量,它也有自己的地址,所以它本身也是可用指針指向的對象。我們能夠將指針的地址存放在還有一個指針中,如:

int i = 5000;

int *pi = &i;

int **ppi = π

此時的ppi即是一個指向指針的指針,下圖表示了這些對象:

                          

i的地址爲108,pi的內容就是i的地址,而pi的地址爲104,ppi的內容即是pi的地址。對ppi解引用照常會得到ppi所指的對象,所獲得的對象是指向int型變量的指針pi。想要真正地訪問到i.,必須對ppi進行兩次解引用,如以下代碼所看到的:

printf("%d", i );

printf("%d", *pi );

printf("%d", **ppi );

以上三條語句的輸出均爲5000。

 

https://www.cnblogs.com/mfrbuaa/p/3756342.html

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