【原創】淺談指針(五)const和指針


前言

過了幾個月再次更新。最近時間也不多了,快要期中考試了,暫且先少寫一點吧。
本文僅在博客園發布,如在其他平台發現均為盜取,請自覺支持正版。

練習題

我們先來看幾道題目。如果這幾道題都不會的話,就先好好復習我寫的前四篇文章吧,這一章是肯定看不懂的。

  • 1.使用指針編寫swap函數。(經典例題)
答案

void swap(int *a,int *b){
int t=*a;*a=*b;*b=t;
}

  • 2.已知數組a[10][10],交換該數組的第1和第3行。
答案 實際上,二維數組的每一行都是一個單獨的數組,二維數組的本質就是“數組的數組”。因此,可以使用memcpy進行數組拷貝。

int temp[10];
memcpy(temp,a[0],10*sizeof(int));
memcpy(a[0],a[2],10*sizeof(int));
memcpy(a[2],temp,10*sizeof(int));

const

const含義

const是constant的縮寫,意為“常量”,事實上我們也經常用const定義常量。
但是在C語言(這里不是C++),const的含義是“只讀變量”。也就是說,const就是普通變量。
我們做一個實驗確認一下。(務必采用C語言編譯)

#include<stdio.h>
int main(){
    int *p;
    const int a=5;
    printf("a..%d",a);
    p=&a;
    *p=10;
    printf("a..%d",a);
}

先說一下C++為什么不通過編譯,因為C++對於類型比較嚴格,編譯上述代碼會出這個錯誤:

error: invalid conversion from 'const int' to 'int' [-fpermissive]
因此,如果手頭只有C++環境的話,請務必開-fpermissive選項。

在C語言下,輸出結果是a..5和a..10。在C++下,即使開了fpermissive,結果仍然是a..5和a..5。
我們來閱讀一下程序。我們使用指針的形式,將a的地址賦值給p,那么p所指向的就是a。但是由於p不帶const(const指針的問題將會於下一節敘述),*p可以被修改,那么a就理所當然被修改為10了。
但是在C++中,const就是指常量,在處理a的時候,編譯器會自動的把a理解為5,不再去讀取a所在的內存了。因此,即使a對應的內存被修改,a輸出結果仍然為5。
如果把第二個printf語句中,a改為*p,輸出為10。這再次證明了C++這一特性。

const內存區域

如果把const int a一句放到main以外成為全局變量,結果又會如何?大家可以自行嘗試一下。

結果是運行時錯誤,segmentation fault段錯誤。
這是因為,全局變量的const,存儲的區域是配置在內存的只讀區域的,修改會出問題。而局部變量存儲的區域在棧上,和其他普通變量在一起,因此可以任意修改。

如果嘗試輸出全局變量和局部變量的地址,我們發現,兩個地址相差很遠。
0x402004 0x7ffd9a34094c

const和指針

聲明部分

(以下轉自我之前寫的C語言常見誤區)
關於const和指針連在一起,經常讓初學者們摸不着頭腦。
例如下面幾句:

const char *p
char const *p
char* const p
const char* const p

它們各有什么區別?
我這里曾經從《征服C指針》看到了幾條非常好的內容,在此給大家分享一下:

因為C語言是美國人發明的,最好還是用英語來讀(聲明語句)。
規則:從后往前倒序,如果遇到*號,就加上“pointer to”,如果有const,就追加“read-only”。
const在前面和在后面完全相同。

例如,對const char *p進行翻譯:
首先看到p:p is
然后是*:p is pointer to
然后是char:p is pointer to char
然后是const:p is pointer to read-only char
翻譯為中文:p是指向只讀的char的指針

按照這種方式解釋,我們對上面四個語句解釋如下:

p is pointer to read-only char
p is pointer to read-only char
p is read-only pointer to char
p is read-only pointer to read-only char

照這樣,我們得出結論:
const char* p 和char const* p含義完全相同,表示指向的字符是不可變的。
char* const p表示指針自身不可變,指向的字符可變。
而最后一個,指向的字符和指針自身都不可變。

應用

定義字符串常量,我們一般使用:

const char *str=...

這類的語句。指向的字符是不可改變的。

但注意下面的代碼:

#include<stdio.h>
#include<string.h>
struct test{
	int a,b;
	char str[10];
};
int main(){
    const struct test a={1,2,"hello"};
	strcpy(a.str,"abc");
	printf("%s",a.str);
}

雖然結構體a是const的,因此str本身不可改變,但是str指向的字符仍然可以改變!圖示如下:

函數參數的const

比較簡單。例如strcpy的聲明:

void strcpy(char *dest, const char *src);

在此處,const表示在函數內部,src的值不可改動。並非表示傳入的參數一定是常量。
很多函數都包含輸入參數和輸出參數。與其使用繁雜的注釋,例如:

/*
src (i) 參數提供的輸入字符串
dest (o) 復制到的字符串
*/

使用i,o等標記,還不如使用const,后者在函數中不小心修改src的時候,還會發出警告。
以上參考《征服C指針》。
全文完。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM