網站首頁 編程語言 正文
指針的賦值
問題
將一個類型為 char** 的值賦值給一個 const char** 類型的對象是否合法呢?
先說結果,在vs的環境下,編譯器不會報錯也不會有任何警告。
但在linux環境下用gcc編譯就會出現下面的警告:
warning: assignment from incompatible pointer type
警告:來自不兼容指針類型的賦值
為了代碼的可移植性我們顯然不能寫出這樣的代碼,下面就讓我們一步步探索這其中的奧妙。
首先來了解ANSI C有關標準
ANSI C 有關簡單賦值的標準
要使賦值形式合法,必須滿足下列條件之一:
- 1.兩個操作數都是指向有限定符或無限定符的相容類型的指針
- 2.?左邊指針所指向的類型必須具有右邊指針所指向類型的全部限定符
還有一個關于類型的說明:
const float* 類型不是一個有限定符的類型——它的類型是 “指向一個具有 const 限定符的 float 類型的指針”,也就是說 const 限定符是修飾指針所指向的類型,而不是指針本身。
問題解決
在解決問題之前,我們先來看一組簡單的。
char* 和 const char*
char* 和 const char* 是匹配的。它之所以合法,是因為在下面的代碼中:
char* cp; const char* cpp; cpp = cp;
- 左操作數是一個指向有const限定符的char的指針;
- 右操作數是一個指向沒有限定符的char的指針;
- char類型與char類型是相容的,左操作數所指向的類型具有右操作數所指向類型的限定符(無),再加上自身的限定符(const)。
注意,反過來就不能進行賦值。
char* cp; const char* cpp; cp = cpp; //此時左操作數不具有右操作數的const限定符
char** 和 const char**
由上面的知識我們可以得知,char** 和 const char** 都是沒有限定符的指針類型,但他們的指向的類型不一樣(前者指向char*,后者指向const char*),這違反了上面賦值標準的第一條,所以它們是不相容的。
用這種方式理解這個有一點困難。可以用下面這種方法進行理解:
char** pp1; const char** pp2; pp2 = pp1;
- 左操作數的類型是 const char**,它是一個指向 const char* 類型的指針,而 const char* 是一個沒有限定符的指針,它指向一個帶有 const 限定的 char 類型;
- 右操作數的類型是 char**,它是一個指向 char* 的指針,而 char* 是一個沒有限定符的指針,它指向一個沒有限定符的 char 類型。
const char* 和 char* 是相容的,而且他們本身沒有限定符,所以符合標準的約束條件,兩者之間的賦值是合法的。但 const char** 和 char** 之間的關系又有不同,雖然二者都沒有限定符,但二者所指向的對象類型不相容,所以不能進行賦值。
const修飾
const修飾變量
首先,關鍵字const并不能把變量變成常量!在一個符號前加上const限定符只是表示這個符號不能被賦值。也就是說const修飾的變量是只讀的,不可以被直接修改,但它不能防止被間接修改。
例如:
#include <stdio.h> int main() { const int i = 10; int* p = &i; printf("before:%d\n", i); *p = 20; printf("after:%d\n", i);//這里打印值變成了20,說明可以間接修改 return 0; }
const修飾指針
const修飾指針變量有多種位置,下面我們將逐個介紹。
const int* p
注:const int* p 與 int const?p 寫法不同,作用是一樣的。
這種寫法的意思是:const修飾p,不能通過解引用(p)的方式直接修改所指向的變量,但可以通過改變指針指向的方式來修改p。
例如:
#include <stdio.h> int main() { //通過下方直接解引用的方式來修改編譯器會直接報錯 //int i = 10; //const int* p = &i; //*p = 20; int i = 10; const int* p = &i; printf("before:%d\n", *p); int j = 20; p = &j;//通過這樣改變p的指向,可以間接修改*p值 printf("after:%d\n", *p); return 0; }
int* const p
這種寫法的意思是:const修飾p,不能通過改變指針指向的方式修改*p的值,但可以通過解引用(*p)的方式直接修改所指向的變量。
例如:
#include <stdio.h> int main() { int i = 10; int* const p = &i; printf("before:%d\n", *p); *p = 20;//不能改變p的指向,但可以直接解引用修改值 printf("after:%d\n", *p); return 0; }
const int* const p
這種寫法是同時修飾p和*p,既不能改變p的指向,也不能用解引用直接修改。
總結
原文鏈接:https://blog.csdn.net/qq_40080842/article/details/122940866
相關推薦
- 2022-06-25 Android開發MediaCodec和lamemp3多段音頻截取拼接_Android
- 2022-01-30 visibilitychange事件在移動端開發的使用
- 2022-04-02 C語言對冒泡排序進行升級介紹_C 語言
- 2023-02-14 詳解C/C++?Linux出錯處理函數(strerror與perror)的使用_C 語言
- 2022-06-28 ASP.NET?WebAPI導出CSV_實用技巧
- 2022-03-14 stream實現list根據對象中多個屬性分組,并取分組后最新數據
- 2022-12-15 Python?OpenCV中cv2.minAreaRect實例解析_python
- 2022-04-07 Nginx各個模塊的配置及常用配置選項_nginx
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支