|
imjn4va1afi640332021.gif (3.61 KB, 下載次數(shù): 1)
下載附件
保存到相冊(cè)
imjn4va1afi640332021.gif
2024-9-14 17:30 上傳
關(guān)注、星標(biāo)公眾號(hào),直達(dá)精彩內(nèi)容
const基本介紹const是constant的簡(jiǎn)寫(xiě),用來(lái)定義常量,如果一個(gè)變量被const修飾,那么它的值就不能再被改變。
const與define的區(qū)別1、define是預(yù)編譯指令,定義的宏是在預(yù)處理階段展開(kāi)的,而const是普通變量的定義,是只讀變量,且是在編譯運(yùn)行階段使用的。2、define定義的是常量,define定義的宏在編譯后消失了,它不占用內(nèi)存,而const定義的常變量本質(zhì)上仍然是一個(gè)變量,具有變量的基本屬性,有類(lèi)型、占用存儲(chǔ)單元,除了不能作為數(shù)組的長(zhǎng)度,用const定義的常變量具有宏的優(yōu)點(diǎn),而且使用更方便。3、define定義的對(duì)象沒(méi)有數(shù)據(jù)類(lèi)型,編譯器只能機(jī)械地進(jìn)行字符替換,沒(méi)有類(lèi)型安全檢查,即會(huì)出現(xiàn)“邊際問(wèn)題”或者是“括號(hào)問(wèn)題”。而const定義的是變量,有數(shù)據(jù)類(lèi)型。
const作用1、可以用來(lái)修飾變量,修飾函數(shù)參數(shù),修飾函數(shù)返回值,且被const修飾的東西,都受到強(qiáng)制保護(hù),可以預(yù)防其它代碼無(wú)意識(shí)的進(jìn)行修改,從而提高了程序的健壯性(是指系統(tǒng)對(duì)于規(guī)范要求以外的輸入能夠判斷這個(gè)輸入不符合規(guī)范要求,并能有合理的處理方式。ps:即所謂高手寫(xiě)的程序不容易死);2、使編譯器保護(hù)那些不希望被修改的參數(shù),防止無(wú)意代碼的修改,減少bug;3、增強(qiáng)代碼的可讀性,給讀代碼的人傳遞有用的信息,聲明一個(gè)參數(shù),是為了告訴用戶這個(gè)參數(shù)的應(yīng)用目的。
const用法介紹1、修飾局部變量、全局變量及字符串常量示例代碼:
#include
#include
#include
const int a = 10; //const修飾的全局變量放在常量區(qū)
//1.const修飾的全局變量,即使語(yǔ)法通過(guò),但是運(yùn)行的時(shí)候會(huì)受到常量區(qū)的保護(hù),段錯(cuò)誤,運(yùn)行失敗
void test01()
{
//a = 100; //直接修改語(yǔ)法不通過(guò)
int *p = &a;
*p = 100; //間接修改語(yǔ)法通過(guò),運(yùn)行時(shí)產(chǎn)生段錯(cuò)誤
printf("a %d
",a);
}
//2.const修飾的局部變量
void test02()
{
const int b = 10; //分配到棧上
//b = 100; //直接修改語(yǔ)法不通過(guò)
//c語(yǔ)言下稱(chēng)為偽常量
int *p = &b;
*p = 100;
printf("b %d
",*p); //間接修改成功
//int a; 偽常量是不可以初始化數(shù)組的
}
//3.字符串常量
void test03()
{
char *p1 = "hello world";
char *p2 = "hello world";
char *p3 = "hello world";
printf("%s
",p1);
printf("%s
", p2);
printf("%s
", p3);
printf("%s
",&"hello world"); //四個(gè)輸出的結(jié)果一樣
//p1[0] = 'z'; //不允許修改字符串常量
printf("p1[0] %c
",p1[0]); //可以輸出
}
int main()
{
// test01();
// test02();
test03();
return 0;
}
const修飾的普通變量:定義的時(shí)候就要給它賦初值,之后哪怕是賦相同值都不行。const修飾的局部變量還是變量,直接修改編譯器報(bào)錯(cuò),可以間接修改,存放在棧區(qū),代碼塊結(jié)束時(shí)釋放。
const修飾全局變量:直接修改編譯器報(bào)錯(cuò),間接修改編譯器也許會(huì)通過(guò),但運(yùn)行時(shí)會(huì)報(bào)錯(cuò)(段錯(cuò)誤)。const修飾的全局變量存放在全局(靜態(tài))存儲(chǔ)區(qū),編譯期最初將其保存在符號(hào)表中,第一次使用時(shí)為其分配內(nèi)存,在程序結(jié)束時(shí)釋放。
const修飾字符串常量:字符串常量位于文字常量區(qū)(也有文章歸類(lèi)于代碼區(qū)),本身就不允許被修改,如果沒(méi)有const的修飾,我們可能會(huì)在后面有意無(wú)意的修改字符串常量,這樣會(huì)導(dǎo)致對(duì)只讀內(nèi)存區(qū)域的賦值,然后程序會(huì)立刻異常終止。有了const,這個(gè)錯(cuò)誤就能在程序被編譯的時(shí)候就立即檢查出來(lái),這就是const的好處。讓邏輯錯(cuò)誤在編譯期被發(fā)現(xiàn)。
2、修飾指針常量指針和指針常量傻傻分不清楚,以下方法幫助你來(lái)區(qū)分二者:區(qū)分常量指針和指針常量的關(guān)鍵就在于星號(hào)的位置,我們以星號(hào)為分界線。
如果const在星號(hào)的左邊,則為常量指針如果const在星號(hào)的右邊則為指針常量如果我們將星號(hào)讀作‘指針’,將const讀作‘常量’的話,內(nèi)容正好符合。
int const * num;是常量指針,就是*num指向的數(shù)據(jù)不可以改,num指向的地址可以修改,int const num;是指針常量,就是num指向的地址不可以修改,num指向的數(shù)據(jù)可以修改。代碼示例:
//第一種,常量指針
const int *p1; //p本身不是const的,而p指向的變量是const
int const *p2; //p本身不是const的,而p指向的變量是const
#include
int main()
{
int a = 5;
int b = 20;
const int *p = &a;
// *p = 100; //編譯器報(bào)錯(cuò)
p = &b; //完全可以
printf("%d
",*p); //間接修改成功
return 0;
}
需要注意的是以下兩點(diǎn):
1、常量指針說(shuō)的是不能通過(guò)這個(gè)指針改變變量的值,但是還是可以通過(guò)其他的方式來(lái)改變變量的值的。
2、常量指針指向的值不能改變,但是這并不是意味著指針本身不能改變,常量指針可以指向其他的地址。
//第二種,指針常量
int* const p3; //p本身是const的,而p指向的變量不是const
#include
int main()
{
int a = 5;
int b = 20;
int *p = &a;
int* const n = &a;
// n = &b; //error: assignment of read-only variable ‘n’
*p = 8;
printf("%d
",a);
return 0;
}
指針常量是指指針本身是個(gè)常量,不能在指向其他的地址,需要注意的是,指針常量指向的地址不能改變,但是地址中保存的數(shù)值是可以改變的,可以通過(guò)其他指向該地址的指針來(lái)修改。
//第三種
const int* const p4; //p本身是const的,而p指向的變量也是const
是以上兩種的結(jié)合,指針指向的位置不能改變并且也不能通過(guò)這個(gè)指針改變變量的值,但是依然可以通過(guò)其他的普通指針改變變量的值。
修飾函數(shù)的參數(shù)const修飾參數(shù)是為了防止函數(shù)體內(nèi)可能會(huì)修改參數(shù)原始對(duì)象。因此,有三種情況可討論:
1、函數(shù)參數(shù)為值傳遞:
值傳遞(pass-by-value)是傳遞一份參數(shù)的拷貝給函數(shù),因此不論函數(shù)體代碼如何運(yùn)行,也只會(huì)修改拷貝而無(wú)法修改原始對(duì)象,這種情況不需要將參數(shù)聲明為const。例如:void func(int x)不用寫(xiě)成void func(const int x)
2、函數(shù)參數(shù)為指針:
指針傳遞(pass-by-pointer)只會(huì)進(jìn)行淺拷貝,拷貝一份指針給函數(shù),而不會(huì)拷貝一份原始對(duì)象。根據(jù)上面對(duì)指針常量、常量指針等討論,同樣分為三種情況:
2.1 防止修改指針指向的內(nèi)容
典型C庫(kù)函數(shù):char *strcpy(char *dest, const char *src);
2.2 防止修改指針指向的地址
void swap ( int * const p1 , int * const p2 );指針p1和指針p2指向的地址都不能修改。
2.3 防止修改指針指向的內(nèi)容和地址
4.修飾函數(shù)的返回值1、如果函數(shù)返回值采用“值傳遞方式”,由于函數(shù)會(huì)把返回值復(fù)制到外部臨時(shí)的存儲(chǔ)單元中,加const 修飾沒(méi)有任何價(jià)值。例如把函數(shù)int GetInt(void) 寫(xiě)成const int GetInt(void)是沒(méi)有意義的。
2、如果給以“指針傳遞”方式的函數(shù)返回值加 const 修飾,那么函數(shù)返回值(即指針)的內(nèi)容不能被修改,該返回值只能被賦給加const 修飾的同類(lèi)型指針。
const char * GetString(void);
char *str = GetString(); //error: conflicting types for ‘str’
const char *str = GetString(); //這種用法才是正確的 |
|