和C語言中任何一個部分一樣,指針也有其基本的常識埋涧。本文不會介紹太多基礎(chǔ)的東西,關(guān)于指針的常識模塊也只是一帶而過奇瘦,如有遺忘棘催,請參考相關(guān)書籍。
1.1 變量
變量常常出現(xiàn)于表達式中耳标,當(dāng)變量出現(xiàn)在表達式的左方時醇坝,它表示的是某個地址;而當(dāng)變量出現(xiàn)在表達式的右方時次坡,它表示的是某個地址里存放的值纲仍。例如:
int a = 1;
int b =2; a = b;
其中a = b;中的a表示的是a的地址空間,而b表示的是b的地址空間中的內(nèi)容贸毕。a = b則表示將a的地址空間的修改成b的地址空間中的內(nèi)容郑叠。簡而言之,對于變量來說明棍,出現(xiàn)在賦值表達式的左邊則表示引用其地址乡革,出現(xiàn)在賦值表達式的右邊則表示引用其值。整個表達式的意思就是,把某個地址里的內(nèi)容修改成后面的內(nèi)容沸版。判斷一個賦值表達式是否合法就看賦值的左邊是否是個地址嘁傀,而右邊又是否是個值。
1.2 指針初始化
定義一個指針只是向編譯器申請一個用于存放某個地址的地址空間视粮,而且這個地址空間里的值應(yīng)該是某個地址细办,同時,指針本身也是一個變量蕾殴。由于指針本身也是一個變量笑撞,那么它的默認初值、作用域钓觉、生存周期等都符合變量的特性茴肥。
指針在使用時一定要先初始化:
例如,int *p; 則編譯器會分配一個4字節(jié)的內(nèi)存用于存放p荡灾,但是此時p還未初始化瓤狐,它的值是不確定的。我們可以用&p取出此指針的地址批幌,用p表示該地址中的內(nèi)容础锐,但是,用*p引用該指針?biāo)赶虻淖兞康闹档慕Y(jié)果是不可預(yù)知的荧缘。如果運氣好皆警,會崩掉,如果運氣不好胜宇,就等著程序給你添麻煩吧耀怜。
一般來說指針的使用流程是:
int *p = NULL; //定義并附初值0
int a = 0; p = &a; //使用前賦值
cout<<*p<<endl; //指針引用
p = NULL; //不用時清空
1.3 NULL系列
在C語言中諸如NULL之類的用于幫助程序員理解程序的宏定義\說明有很多,現(xiàn)簡要說明一下桐愉。
NUL:ASCII字符集中的’\0’字符的名字财破,它的字節(jié)模式為全0。事實上从诲,根本就不存在預(yù)定義的符號NUL左痢,如果想要使用,則必須自己定義系洛。#define NUL 0 或 #define NUL '\0'
NULL:標(biāo)識空指針俊性。定義為0 即 #define NULL 0
false:標(biāo)識邏輯0。定義為0 即 #define false 0
true:標(biāo)識邏輯1描扯。定義為1 即#define false 1
1.4 指針常見錯誤
指針最常見的錯誤就是段錯誤了定页。程序在執(zhí)行時會分成許多段,對段的非法操作統(tǒng)稱為段錯誤绽诚。比如典徊,修改只讀段的內(nèi)容杭煎,比如訪問不屬于該程序的段。最為常見的例子就是訪問不屬于該程序的地址空間卒落。
一種好的編程風(fēng)格是在創(chuàng)建指針的時候賦初值NULL羡铲,因為一般而言任何操作系統(tǒng)都會把低位地址留給操作系統(tǒng),把高位地址留給應(yīng)用程序儡毕。當(dāng)應(yīng)用程序中引用地址0時會產(chǎn)生訪問不屬于該程序地址空間的操作也切,此時就會引發(fā)段錯誤。
對于某些要求對界的機器而言腰湾,當(dāng)某種類型的數(shù)據(jù)在內(nèi)存中的存儲地址處在錯誤的邊界上的時候雷恃,此時訪問這個地址會引發(fā)一個總線錯誤。
注:本文中各種特例都是在UNIX系統(tǒng)的gcc編譯器下調(diào)試的檐盟,本文所說的各種術(shù)語也都適用于UNIX系統(tǒng)褂萧,但是對于Windows未必適用押桃。
問題:段錯誤的精確定義是什么葵萎?段錯誤和可執(zhí)行程序的段到底有什么聯(lián)系?
1.5 指針常量
我們可以將一個常量強制轉(zhuǎn)換成指針唱凯,雖然這個操作并沒有太多的意義羡忘,但確實是可以的。例如:
int * a = (int*) 100;
*(int*)100 = 100;
問題:用常量在程序中表示的地址是不是絕對地址磕昼?