由“一個關於指針的小問題”想到的:常量指針與指向常量的指針

         今天在點擊打開鏈接看到一個關於指針的小問題:
#include <iostream>
#include<string.h>
using namespace std;
 
int main()
{
    char *str="AAA";
    str[0]='B';
    cout << str << endl;
    return 0;
}

這段代碼的問題在哪兒呢?乍一看我沒看出問題,通過學習帖子的回覆,還是小有感觸的。


        其實,這就是char *a = "hello" 與 char a[] = "hello"區別。正如一個回覆中所說,第一個把一個常量字符串存入靜態存儲區,並用p指針指向其首位。後續程序可以通過該指針讀取字符串內容,但不能改寫;第二個把字符串複製到棧空間裏,並將此位置命名爲 char p[]。後續程序可以通過字符數組p讀取、更改該字符串,但不能改寫p自身

         因此,當把程序改爲:

#include <iostream>
#include<string.h>
using namespace std;
 
int main()
{
    char str[]="AAA";
    str[0]='B';
    cout << str << endl;
    return 0;
}
就可以得到想要的輸出了。


       看到這裏,我突然想起了以前學過的常量指針與指向常量的指針的概念,遂找出來重新理了一遍,總結如下:

1. 指向常量的指針這樣定義:

const char *pc;
或者

char const *pc;
char *a = "hello" 就屬於這種情況,因爲"hello"屬於靜態存儲區中的常量字符串。其實,在C++中更標準的寫法是const char *a = "hello",前述寫法是屬於兼容C的寫法。在這裏,通過指針a可以讀取字符串,但是不能改寫。對於指針a本身,可以對它重新進行賦值,也就是可以改變它的指向。

2. 常量指針。顧名思義,就是指針本身是常量,不可更改。如下定義:

char * const pc;
可以讀取和改寫pc指向的內容,但是不能改變pc的指向。其實,char a[] = "hello"屬於這一範疇。因爲常量指針除了用" * const "定義外,還有變量的地址、數組名、結構數組名、對象數組名、函數名等。在這裏a就屬於數組名,因此它也是常量指針。所以,對指針a進行重定向的操作是非法的,編譯器會提示“表達式必須是可以修改的左值”。
3. 指向常量的常量指針。如下定義:

const char* const pc; 
這時候,pc指向的內容和pc本身都不能更改。比如

char *const pc = "hello";
中pc其實就屬於指向常量的常量指針。因爲除了顯式的const常量指針說明以外,靜態存儲區的"hello"隱式的告訴了pc指向常量。所以,pc[3] = 'a' 和 pc = 'world' 的操作都是非法的。

       最後,我們再來比較一下char pc[] = "hello" 與 char* const pc = "hello"的區別。請看以下兩段代碼:

#include <iostream>
#include<string.h>
using namespace std;
 
int main()
{
    char pc[] = "hello";
    pc[0]='B';
    cout << pc << endl;
    return 0;
}

#include <iostream>
#include<string.h>
using namespace std;
 
int main()
{
    char* const pc = "hello";
    pc[0]='B';
    cout << pc << endl;
    return 0;
}

第一段代碼可以正常打印出”Bello“,而第二段代碼編譯會有內存訪問衝突。這說明,char pc[] = "hello" 僅僅是常量指針,它將字符串複製到棧空間中,因此pc指向的內容是可更改的;而char* const pc = "hello" 是指向常量的常量指針,"hello"保存在靜態存儲區中,因此pc指向的內容是不能更改的。第二段代碼更改如下,將pc指向棧區,即可正常打印:

#include <iostream>
#include<string.h>
using namespace std;
 
int main()
{
    char str[] = "hello";
    char* const pc = str;
    pc[0]='B';
    cout << pc << endl;
    return 0;
}
發佈了9 篇原創文章 · 獲贊 32 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章