指標恐怕是c語言中最不容易掌握的乙個概念了,但指標又是如此的重要,可以說不會指標,c語言就等於沒學。
指標到底是乙個什麼東西呢?
#include int main()
; char *pch = null;
char *pstr = "hello pointer";
short *pshort = null;
int *pint = null;
float *pfloat = null;
double *pdouble = null;
struct myst* pstruct = null;
printf("sizeof(pch) = %d\n", sizeof(pch));
printf("sizeof(pstr) = %d\n", sizeof(pch));
printf("sizeof(pshort) = %d\n", sizeof(pshort));
printf("sizeof(pint) = %d\n", sizeof(pint));
printf("sizeof(pfloat) = %d\n", sizeof(pfloat));
printf("sizeof(pdouble) = %d\n", sizeof(pdouble));
printf("sizeof(pstruct) = %d\n", sizeof(pstruct));
getchar();
return 0;
}
執行上邊**
在編譯目的為32位系統程式時,指標無論是指向基本資料型別,還是複雜資料型別,它所佔的空間大小始終是4位元組
再把編譯目標設定為64位
同樣指標無論是指向基本資料型別,還是複雜資料型別,它所佔的空間大小始終是8位元組。
1. 最最根本的約定因素就是cpu。如果cpu是32位的,那麼它所能夠尋找的位址範圍就在0 ~ 0xffffffff之間, 在這個區間的位址資料寬度都不會超過32位。指標變數的乙個主要功能就是存放位址資料的,為了能夠存放得下任意有效的位址,那麼在32位cpu並且作業系統也是32位的情況下,指標所佔記憶體寬度自然應該是4位元組。
同理如果cpu是64的。它的定址範圍就是0~0xffffffffffffffff之間,在這個區間的位址資料寬度都不會超過64位,那麼在64位作業系統下,並且生成的程式也是64的,在這程式當中,指標變數所佔記憶體寬度自然應該是8位元組。
2 如果編譯器生成的目標程式是32位的,或者在64位cpu上執行的是32位作業系統。cpu雖然是64位的,但由於程式或作業系統定址能力的限制,這時指標變數所佔記憶體空間就是4位元組32位。 因為64位是相容32位的,所以32位程式和32位系統也能夠正確執行
1 任意型別 * 變數名
例如
int *pint;
double *pdouble;
human *phuman;
2 *號可以寫多個(能寫多少個,沒試過 ^^)
int** p;
human**** h;
char *x
short *y
int* z
x = (char*)1;
y = (short*)2;
z = (int*)3;
指標變數賦值,在宣告乙個指標變數的時候,就已經告訴編譯器,這個變數應該存放的資料是乙個位址,可以從這個位址中獲取乙個指定型別的資料。有了型別說明,編譯器才會知道從那個位址開始應該讀取多少個位元組,並把這些資料解釋為何種型別。所以給乙個指標賦值時,賦值操作符「=」 右邊的資料型別應當和指標宣告的型別相同。如果等號右邊所給的資料型別和指標變數型別不符,那麼編譯器就會報錯。這樣做的原因是為了程式設計的安全和正確性。假設我們指標變數型別為int* 而右邊給的確是乙個short*,如果編譯器不報錯,並編譯通過,程式執行時讀取那塊位址開始的4位元組空間,顯然多讀取了兩個位元組,你怎麼知道多讀的兩個位元組是什麼。如果那多的兩個位元組是另外乙個重要的資料變數呢,這時就會被你的誤操作所修改,導致程式出錯。如果我們的產品是為醫療裝置做開發,很有可能會引起一場醫療事故。如果我們為某某原子機構做開發呢,有可能乙個蘑菇雲就誕生了!!! 所以指標變數賦值要保證兩邊型別一致,除非你知道自己為什麼這樣做。當你想把等號右邊型別不符的資料強制賦值給指標,那就應該告訴編譯器,編譯器老哥,把這個資料當作和指標型別一樣的型別處理,就這麼幹。既然我們程式設計師已經發號師令了,那這時編譯器也就沒什麼話說了。
指標就是為了定址資料的,能過指標獲取了乙個字串的首位址,根據字串的特性我們就可以讀出整條字串的內容。同樣如果獲取了乙個整型陣列的首位址,並且知道陣列的大小,那麼就可以高效訪問陣列中任一元素。我們獲得了有效資料的乙個位址,32位或64位,而僅僅通過這32位或64位資料就可以實現對大量資料的操作,是不是很簡潔高效。有點類似電視機的遙控器,小小的遙控器在手,多大的電視都要聽我的話,對吧
pstr = "abcdefg"; 這條c語句的意思就是把常量字串第乙個字元的位址賦值給指標變數pstr;
c語言中只要是出現常量字串的位址它返回的就是這個字串第乙個字元的位址。前邊這條變數賦值更應該這樣寫
pstr = (char*)0x0040c0dc; 其實背後編譯器也是這麼幹的。但直接用數字表達不夠直觀,二我們也不知道「abcdefg」應該存放在哪個位置
所以寫成pstr = "abcdefg"; 讓編譯器去給這個常量字串分配空間,並返回位址給我們的指標變數。
同樣思考下printf("%d", 23); 實際上我們向printf函式中傳入了兩個引數,乙個是字串"%d"的首位址,乙個是23
pstr++; 指標自身加1 。這時指標變數中的數值已經修改為0x0040de;在計算機中查詢這塊位址並取一位元組,再把這一位元組資料轉換成
字元所以輸出b
pstr + 3 就相當於 pstr中的數值 + sizeof(指標指向型別)*3, 所以 0x0040de + 1 * 3 得到位址0x0040c0e1, 輸出結果為e
pnum用陣列首位址初始化,所以此時pnum變數中存放的數值為0x0018ff44
pnum++ 這時指標自加顯然已經不是簡單的加1操作了。我們看到這時指標增加了4個位元組,如果只增加乙個位元組,顯然我們會得到錯誤
的結果。為了正確定址資料,所以宣告指標時要指定一種型別,知道了型別資訊,那麼編譯器自然知道如何定址和解釋資料了。
pnum + 3 相當於0x0018ff48 + 3 * sizeof(int) 所以最張輸出結果為5
結論: 指標是可以進行加減操作的。目的是方便資料定址 通過以上觀察我們可以得出這樣乙個公式
指標 +/- 數字 = 指標內容 +/- 數字*(sizeof(指標型別))
那麼指標乘除顯然沒有任何意義。
C語言指標1
陣列與指標 陣列的名字是第一元素的位址。include int main printf str 0 的位址是 p n str 0 輸出 str 0 的位址是 000000000062fdc0陣列相鄰每一元素之間相差值 資料型別的寬度 include int main float b 3 double...
C語言指標1
1 取位址符 2 雙目運算子 例如a b 按位於 指標 位址 int p 定義整型指標變數 double p1 定義浮點型指標變數 int a 10 整型變數存放整型值 double b 23.3 浮點型變數存放浮點數 int p a 整型指標變數存放整型位址 指標 p 為間接訪問符,也稱為解引用 ...
C語言指標1
計算機中所有的資料都必須放在記憶體中,不同型別的資料占用的位元組數不一樣,例如 int 占用4個位元組,char 占用1個位元組。為了正確地訪問這些資料,必須為每個位元組都編上號碼,就像門牌號 身份證號一樣,每個位元組的編號是唯一的,根據編號可以準確地找到某個位元組。先看這樣一段 定義乙個整型變數a...