一起來(lái)練習(xí)C++的指針
在C++中,const作用于指針時(shí),可以看做是對(duì)指針權(quán)限的限制。這里我們先把指針的權(quán)限歸為兩種,分別為指向權(quán)限和修改權(quán)限。(ps:以上是為了理解方便,實(shí)際并沒(méi)有如此規(guī)定)
int a = 10, b = 20; int* p = &a; p = &b; // 改變指向的權(quán)限 ? *p = 30; // 修改內(nèi)存的權(quán)限 ? const int* cp = &a; // 限制修改權(quán)限 //*cp = 100; // error:表達(dá)式必須是可修改的左值 修改 ? cp = &b; // ok. 指向 ? int* const pa = &a; // 限制指向權(quán)限 *pa = 100; // ok. 修改 ? //pa = &b; // error:表達(dá)式必須是可修改的左值 指向 ?
指針的賦值一般遵守權(quán)限縮小式的賦值。例如,我有一本書(shū),我有使用權(quán)限(我可以看,可以做筆記),借給你后你只有閱讀權(quán)限(只能看,不能做筆記)。當(dāng)然,如果我們關(guān)系好,我可以賦予你使用權(quán)(你擁有讀寫(xiě)的權(quán)利)。同樣的,指針的賦值也是如此。
int a = 10; int* p = &a; // int* <== int * int* q = p; // int* <== int* const int* cp = p; // const int* <== int* 權(quán)限縮小,? int* const pa = p; // int* <== int* 注意:int* const pa;是“int*”類型 //int* p1 = cp; // error:int* <== const int * 權(quán)限放大,? int* p2 = pa; // ok. int* <== int*
我們可以得出一級(jí)指針賦值的公式
int * <== int * // int* 包含 int* 和 int* const類型 int const * <== int * // int const * <=等同=> const int * // 以上公式反過(guò)來(lái)賦值就是錯(cuò)誤的..
練習(xí)一:一級(jí)指針指向練習(xí)題
題目一:下列表達(dá)式語(yǔ)句賦值錯(cuò)誤的是?
int a = 10; const int* p = &a; int* q = p; int a = 10; int* const p = &a; int* q = p; int a = 10; int* const p = &a; int* const q = p; int a = 10; int* const p = &a; const int* q = p;
答案:(鼠標(biāo)選中查看)
??錯(cuò)誤:A,正確:B、C、D??
解析:
int a = 10; const int* p1 = &a; int* q1 = p1; // error:無(wú)法從const int * 轉(zhuǎn)為 int * /* 分析: int* <= cosnt int* */ int* const p2 = &a; int* q2 = p2; /* 分析: int* <= int* */ int* const p3 = &a; int* const q3 = p3; /* 分析: int* <= int* */ int* const p4 = &a; const int* q4 = p4; /* 分析: cosnt int* <= int* */
練習(xí)二:二級(jí)指針指向練習(xí)題
題目二:下列表達(dá)式語(yǔ)句錯(cuò)誤的有。
// 選項(xiàng)A int a = 10; int* p1 = &a; const int** q1 = &p1; // 選項(xiàng)B int a = 10; int* p2 = &a; int* const* q2 = &p2; // 選項(xiàng)C int a = 10; int* p3 = &a; int** const q3 = &p3; // 選項(xiàng)D int a = 10; int* const p4 = &a; int** q4 = &p4; // 選項(xiàng)E int a = 10; const int* p5 = &a; int* const* q5 = &p5;
答案:(鼠標(biāo)選中查看)
??錯(cuò)誤:A、D、E,正確:B、C??
A選項(xiàng);
錯(cuò)誤; 注:如果const修飾的是二級(jí)指針,我們需要對(duì)二級(jí)指針的逐層解引用進(jìn)行分析。
int* p1 = &a; const int** q1 = &p1; //error 無(wú)法從“int * *”轉(zhuǎn)換為“const int** ”
int* p1 = &a;
p1的類型為int*
取地址為 int **
const int** q1 = &p1;
q1的類型為 const int **
則指針賦值過(guò)程為 const int ** <= int* *
分析:
- const作用于(**q1),修飾二級(jí)指針。表示不可通過(guò)q1對(duì)
a
的值進(jìn)行修改。 - *q1 解引用一次后,為一級(jí)指針,即 p1 。但是 p1 存在對(duì)
a
修改的風(fēng)險(xiǎn),因此無(wú)法直接賦值。
修改方案:
- 方案一:直接限定一級(jí)指針p1。保證p1不會(huì)修改a的值,即
const int * p1= &a;
const int** q1 = &p1;
- 方案二:間接限定q1,使其指向時(shí)縮小權(quán)限,對(duì)解引用后的(*q1)修改的權(quán)限做出限制,如:
const int * const * q1;
// 方案一 const int* p12 = &a; const int** q12 = &p12; // 方案二 int* p11 = &a; const int* const* q11 = &p1;
B選項(xiàng);
正確; 注:如果const修飾的是一級(jí)指針,我們可以拋開(kāi)二級(jí)指針的表象,但看一級(jí)指針的賦值操作是否正確。如本例。
int* p2 = &a; int* const* q2 = &p2; /* 分析: int* const* <== int* * const修飾 *q2,即cosnt修飾一級(jí)指針 cosnt* <== * // 去掉前面的 int* <= int* int const * <== int * // 添加一個(gè)任意類型,如int 如??所示,這是一個(gè)權(quán)限縮小的一級(jí)指針賦值,? */
C選項(xiàng);
正確; 注:如果兩邊類型相同,則無(wú)需進(jìn)行判斷。如本例。
int* p3 = &a; int** const q3 = &p3; cout << typeid(q3).name() << endl; //輸出 q3 類型 int * * /* 分析: int**const <== int* * 即 int** <== int* * 兩邊類型相同,無(wú)需進(jìn)行特殊判斷,? */
ps:如果const修飾的參數(shù)右邊無(wú)“*”號(hào),則該cosnt不作用于類型。如:
int n = 10; // 使用typeid(valtypr).name() 輸出變量類型 int const* p1 = &n; // int const * int* const p2 = &n; // int * // 忽略const int* p = &n; int** q = &p; //int const** q1 = &p; int const* const* q1 = &p; // int const* const* int* const* q2 = &p; // int* const* int** const q3 = &p; // int** // 忽略cosnt
D選項(xiàng);
錯(cuò)誤; 同B選項(xiàng)相同,對(duì)于const修飾的一級(jí)指針進(jìn)行判即可。
int* const p4 = &a; int** q4 = &p4; //error "int *const *"類型的值不能用于初始化"int **類型的實(shí)體
int* const p4 = &a;
類型為 int*
,因?yàn)閏onst的存在,取地址后類型為 int * const *
int** q4 = &p4;
類型為 int**
則指針賦值過(guò)程為 int** <== int* const*
分析:
- const作用于(p4),修飾一級(jí)指針。則我們忽略沒(méi)有const修飾的部分。即
* <== const*
,//忽略 int 部分,該部分賦值時(shí)權(quán)限沒(méi)有發(fā)生變化。int* <== int const *
,給指針確定一個(gè)類型,如“int” 類型 - 如??,我們可以看到,該表達(dá)式語(yǔ)句想從int const* 類型處,獲得一個(gè) int* 類型的賦值,也就是說(shuō)這是權(quán)限放大式的賦值。錯(cuò)誤原因:該賦值會(huì)使得 int* 類型指針對(duì)常量(int const* 所指向的值)產(chǎn)生修改的風(fēng)險(xiǎn)。
修改方案:
- 把
int* <== int const *
型賦值改成int const* <== int const *
類型賦值即,int*const* q4 = &p4;
E選項(xiàng);
錯(cuò)誤; 注:如果賦值兩邊都有const時(shí),各論各的分析,如下。
const int* p5 = &a; int* const* q5 = &p5; //error 無(wú)法從"const int **"轉(zhuǎn)換為"int *const *"
分析:
- 省略分析過(guò)程等賦值類型為
int* const* <== const int* *
- 分情況分析:
- 提取指針左邊部分:
int* <== const int*
,錯(cuò)誤 ? - 提取指針右邊部分:
cosnt * <== *
即int const * <== int *
,正確 ?
- 提取指針左邊部分:
- 綜上,錯(cuò)誤 ?。
修改方案:
1.修改指針左邊類型:int* <== const int*
⇒ int* <= int*
2.修改指針左邊類型:int* <== const int*
⇒ const int* <= const int*
//1 int* <= int* int* p51 = &a; // const int* p5 ? int* p51 int* const* q51 = &p51; //2 const int* <= const int* const int* p52 = &a; const int* const* q52 = &p52; // int* const* q5 ? const int* const* q52
方法總結(jié):
對(duì)于二級(jí)指針的賦值操作判斷,看const位置、主要有以下兩種情況:
- 如果 const修飾的是二級(jí)指針 如:
int const **
,如選項(xiàng)A。我們需要考慮其解引用情況。cosnt修飾二級(jí)指針?biāo)赶虻闹禐槌A?,但是由于一次解引用后的指針?huì)存在修改常量的風(fēng)險(xiǎn),因此我們需要限制該指針與常量之間進(jìn)行過(guò)度的一級(jí)指針- 針對(duì)此類二級(jí)指針,我們只需記住合法的賦值為等式兩邊需同時(shí)有const ,
const int* cosnt* <== int**
或 左邊等式有兩個(gè)cosnt ,const int* cosnt* <== int**
。
- 如果 const修飾的是一級(jí)指針或其他 如:
1.const修飾的是一級(jí)指針,int * const *
,如選項(xiàng)B。單獨(dú)剝離出含cosnt類型的一級(jí)指針類型進(jìn)行分析
2.即修飾一級(jí)指針又修飾二級(jí)指針 如, int cosnt * cosnt *
3.無(wú)const修飾 如, int**
或 int ** cosnt
,如選項(xiàng)C、選項(xiàng)D
- 針對(duì)此類二級(jí)指針,通過(guò)一級(jí)指針的比較進(jìn)行比較即可。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
C++中std::count函數(shù)介紹和使用場(chǎng)景
std::count函數(shù)是一個(gè)非常實(shí)用的算法,它可以幫助我們快速統(tǒng)計(jì)給定值在指定范圍內(nèi)的出現(xiàn)次數(shù),本文主要介紹了C++中std::count函數(shù)介紹和使用場(chǎng)景,感興趣的可以了解一下2024-02-02Visual Studio 2019 DLL動(dòng)態(tài)庫(kù)連接實(shí)例(圖文教程)
這篇文章主要介紹了Visual Studio 2019 DLL動(dòng)態(tài)庫(kù)連接實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03詳解如何利用C++實(shí)現(xiàn)Mystring類
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)MyString的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08C++中靜態(tài)成員函數(shù)訪問(wèn)非靜態(tài)成員的實(shí)例
這篇文章主要介紹了C++中靜態(tài)成員函數(shù)訪問(wèn)非靜態(tài)成員的實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-07-07C++編譯錯(cuò)誤variable-sized?object?may?not?be?initiali問(wèn)題
這篇文章主要介紹了C++編譯錯(cuò)誤variable-sized?object?may?not?be?initiali問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05c++11 符號(hào)修飾與函數(shù)簽名、函數(shù)指針、匿名函數(shù)、仿函數(shù)、std::function與std::bind
這篇文章主要介紹了c++11 符號(hào)修飾與函數(shù)簽名、函數(shù)指針、匿名函數(shù)、仿函數(shù)、std::function與std::bind,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05C語(yǔ)言 數(shù)據(jù)結(jié)構(gòu)之鏈表實(shí)現(xiàn)代碼
這篇文章主要介紹了C語(yǔ)言 數(shù)據(jù)結(jié)構(gòu)之鏈表實(shí)現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2016-10-10