C語(yǔ)言 指針的初始化賦值案例詳解
1、指針的初始化
指針初始化時(shí),“=”的右操作數(shù)必須為內(nèi)存中數(shù)據(jù)的地址,不能夠是變量,也不能夠直接用整型地址值(可是int*p=0;除外,該語(yǔ)句表示指針為空)。此時(shí),*p僅僅是表示定義的是個(gè)指針變量,并沒有間接取值的意思。
比如:
int a = 25; int *ptr = &a; int b[10]; int *point = b; int *p = &b[0];
假設(shè):
int *p; *p = 7;
則編譯器(vs2008)會(huì)提示The variable 'p' is being used without being initialized.即使用了未初始化的變量p。
由于p是指向7所在的地址,*p = 7給p所指向的內(nèi)存賦值,p沒有賦值,所以p所指向的內(nèi)存位置是隨機(jī)的,沒有初始化的。
int k; int *p; p = &k; //給p賦值 *p = 7; //給p所指向的內(nèi)存賦值,即k= 7
2、指針的賦值
int *p; int a; int b[1]; p = &a; p = b;
指針的賦值,“=”的左操作數(shù)能夠是*p,也能夠是p。
當(dāng)“=”的左操作數(shù)是*p時(shí),改變的是p所指向的地址存放的數(shù)據(jù);
當(dāng)“=”的左操作數(shù)是p時(shí),改變的是p所指向的地址。
數(shù)組的變量名b表示該數(shù)組的首地址,因此p=b;也是正確的
同類型的指針賦值:
int val1 = 18,val2 = 19; int *p1,*p2; p1 = &val1; p2 = &val2; p1 = p2; //注意啦,p1指向了val2,而沒有指向val1
備注:字符串與指針的初始化和賦值
初始化:
char *cp = "abcdefg"; //這個(gè)初始化過程,是將指針cp指向字符串的首地址,而并非傳遞字符串的值。由于,在C語(yǔ)言里面,沒有總體處理一個(gè)字符串的機(jī)制
賦值:
cp = "abcdefg"; *cp=”abcdefg” ;//錯(cuò)誤!字符串常量傳遞的是它的首地址,不能夠通過*cp改動(dòng)該字符串的值,由于該字符串為常量,而它僅僅是簡(jiǎn)單的將指針指向該字符串常量
3、指針常量
在C語(yǔ)言中沒有一種內(nèi)建(built-in)的方法去表示指針常量,所以當(dāng)我們使用它的時(shí)候通常先寫成整型常量的形式,然后再通過強(qiáng)制類型轉(zhuǎn)換把它轉(zhuǎn)換成對(duì)應(yīng)的類型,如:int * , double * , char *等。 所以后面所看到的的做法是不行的: int *p = 0x12345678 ; 正確的方式應(yīng)為:int *p = (int *) 0x12345678; 要注意指針中僅僅能存放地址,不能將一個(gè)非0值整型常量表達(dá)式或者其它非地址類型的數(shù)據(jù)賦給一個(gè)指針,原因就在此。在大多數(shù)計(jì)算機(jī)中,內(nèi)存地址確實(shí)是以無符號(hào)整型數(shù)來表示的,并且多以16進(jìn)制表示,但我們?cè)贑語(yǔ)言中不能用整型數(shù)去表示地址,僅僅能用指針常量來表示,由于它是被用來賦給一個(gè)指針的。
對(duì)于這個(gè)賦值問題還能夠換一個(gè)角度去理解,在C語(yǔ)言中,使用賦值操作符時(shí),賦值操作符左邊和右邊的表達(dá)式類型應(yīng)該是同樣的,假設(shè)不是,賦值操作符將試圖把右邊表達(dá)式的值轉(zhuǎn)換為左邊的類型。所以假設(shè)寫出int *p = 0x12345678 ; 這條語(yǔ)句編譯器會(huì)報(bào)錯(cuò):'=' : cannot convert from ' const int ' to ' int * ' ,由于賦值操作符左邊和右邊的表達(dá)式的類型應(yīng)該同樣,而0x12345678是int型常量,p是一個(gè)指向int型的指針,兩者類型不同,所以正確的方式是:int *p = (int *) 0x12345678 ;
4、指針初始化補(bǔ)充
ANSI C定義了零指針常量的概念:一個(gè)具有0值的整形常量表達(dá)式,或者此類表達(dá)式被強(qiáng)制轉(zhuǎn)換為void *類型,則稱為空指針常量,它能夠用來初始化或賦給不論什么類型的指針。也就是說,我們能夠?qū)?、0L、'/0'、2–2、0*5以及(void *)0賦給一個(gè)不論什么類型的指針,此后這個(gè)指針就成為一個(gè)空指針,由系統(tǒng)保證空指針不指向不論什么對(duì)象或函數(shù)。
ANSI C還定義了一個(gè)宏NULL,用來表示空指針常量。大多數(shù)C語(yǔ)言的實(shí)現(xiàn)中NULL是採(cǎi)用后面這樣的方式定義的:#define NULL ((void *)0)。
對(duì)指針進(jìn)行初始化時(shí)經(jīng)常使用的有下面幾種方式:
- 採(cǎi)用NULL或空指針常量,如:int *p = NULL;或 char *p = 2-2; 或float *p = 0;
- 取一個(gè)對(duì)象的地址然后賦給一個(gè)指針,如:int i = 3; int *ip = &i;
- 將一個(gè)指針常量賦給一個(gè)指針,如:long *p = (long *)0xfffffff0;
- 將一個(gè)T類型數(shù)組的名字賦給一個(gè)同樣類型的指針,如:char ary[100]; char *cp = ary;
- 將一個(gè)指針的地址賦給一個(gè)指針,如:int i = 3; int *ip = &i;int **pp = &ip;
- 將一個(gè)字符串常量賦給一個(gè)字符指針,如:char *cp = “abcdefg”;
對(duì)指針進(jìn)行初始化或賦值的實(shí)質(zhì)是將一個(gè)地址或同類型(或相兼容的類型)的指針賦給它,而無論這個(gè)地址是怎么取得的。要注意的是:對(duì)于一個(gè)不確定要指向何種類型的指針,在定義它之后最好把它初始化為NULL,并在解引用這個(gè)指針時(shí)對(duì)它進(jìn)行檢驗(yàn),防止解引用空指針。另外,為程序中不論什么新創(chuàng)建的變量提供一個(gè)合法的初始值是一個(gè)好習(xí)慣,它能夠幫你避免一些不必要的麻煩。
5、void *型指針
ANSI C定義了一種void *型指針,表示定義一個(gè)指針,但不指定它指向何種類型的數(shù)據(jù)。void *型指針作為一種通用的指針,能夠和其他不論什么類型的指針(函數(shù)指針除外)相互轉(zhuǎn)化而不須要類型強(qiáng)制轉(zhuǎn)換,但不能對(duì)它進(jìn)行解引用及下標(biāo)操作。C語(yǔ)言中的malloc函數(shù)的返回值就是一個(gè)void *型指針,我們能夠把它直接賦給一個(gè)其他類型的指針,但從安全的編程風(fēng)格角度以及兼容性上講,不妨將返回的指針強(qiáng)制轉(zhuǎn)換為所需的類型,另外,malloc在無法滿足請(qǐng)求時(shí)會(huì)通過返回一個(gè)空指針來作為“內(nèi)存分配失敗”的信號(hào),所以要注意返回值指針的判空。
6、指向指針的指針
在指針初始化的第5種方式中提到了用一個(gè)指針的地址來初始化一個(gè)指針。回顧一下上一講的內(nèi)容:指針是一種變量,它也有自己的地址,所以它本身也是可用指針指向的對(duì)象。我們能夠?qū)⒅羔樀牡刂反娣旁谶€有一個(gè)指針中,如:
int i = 5000; int *pi = &i; int **ppi = π
此時(shí)的ppi即是一個(gè)指向指針的指針
i的地址為108,pi的內(nèi)容就是i的地址,而pi的地址為104,ppi的內(nèi)容即是pi的地址。對(duì)ppi解引用照常會(huì)得到ppi所指的對(duì)象,所獲得的對(duì)象是指向int型變量的指針pi。想要真正地訪問到i.,必須對(duì)ppi進(jìn)行兩次解引用,如以下代碼所看到的:
printf("%d", i ); printf("%d", *pi ); printf("%d", **ppi );
以上三條語(yǔ)句的輸出均為5000。
到此這篇關(guān)于C語(yǔ)言 指針的初始化賦值案例詳解的文章就介紹到這了,更多相關(guān)C語(yǔ)言 指針的初始化賦值內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言編程C++旋轉(zhuǎn)字符操作串示例詳解
這篇文章主要為大家介紹了C語(yǔ)言編程中C++旋轉(zhuǎn)字符操作串示例詳解,文中附含詳細(xì)圖文示例代碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-09-09C++?boost?thread庫(kù)用法詳細(xì)講解
Boost是為C++語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供擴(kuò)展的一些C++程序庫(kù)的總稱。Boost庫(kù)是一個(gè)可移植、提供源代碼的C++庫(kù),作為標(biāo)準(zhǔn)庫(kù)的后備,是C++標(biāo)準(zhǔn)化進(jìn)程的開發(fā)引擎之一,是為C++語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供擴(kuò)展的一些C++程序庫(kù)的總稱2022-11-11利用C語(yǔ)言實(shí)現(xiàn)http服務(wù)器(Linux)
本文將利用C語(yǔ)言實(shí)現(xiàn)一個(gè)輕量級(jí)的http服務(wù)器,使用Reactor模式,即主線程只負(fù)責(zé)監(jiān)聽文件描述符上是否有事件發(fā)生,有的話立即將該事件通知工作線程,感興趣的可以了解一下2022-07-07詳解基于C++實(shí)現(xiàn)約瑟夫環(huán)問題的三種解法
約瑟夫環(huán)問題是算法中相當(dāng)經(jīng)典的一個(gè)問題,其問題理解是相當(dāng)容易的,并且問題描述有非常多的版本,并且約瑟夫環(huán)問題還有很多變形,通過這篇約瑟夫問題的講解,一定可以帶你理解透徹2021-06-06C語(yǔ)言實(shí)現(xiàn)單元測(cè)試的示例詳解
單元測(cè)試(unit testing),是指對(duì)軟件中的最小可測(cè)試單元進(jìn)行檢查和驗(yàn)證。這篇文章主要為大家介紹了C語(yǔ)言實(shí)現(xiàn)單元測(cè)試的方法,需要的可以參考一下2022-09-09C語(yǔ)言之整數(shù)劃分問題(遞歸法)實(shí)例代碼
這篇文章主要介紹了C語(yǔ)言之整數(shù)劃分問題(遞歸法)實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-02-02基于c++11的event-driven library的理解
這篇文章主要介紹了基于c++11的event-driven library的理解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02C語(yǔ)言實(shí)現(xiàn)打印數(shù)字金字塔
這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)打印數(shù)字金字塔方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11用C++實(shí)現(xiàn)SLR語(yǔ)法分析程序
大家好,本篇文章主要講的是用C++實(shí)現(xiàn)SLR語(yǔ)法分析程序,感興趣的同學(xué)趕緊來看一看吧,對(duì)你有幫助的話記得收藏一下2022-02-02