伙伴們!我們一起再繼續加油學習關於C指針的後續部分,今天我們要學習的是指針與數組。昨天我們一起學習了linux的安裝以及emacs編輯器的打開輸入保存與退出,以及gdb的最基礎的幾個調試功能,大家都熟練掌握了嗎?有些朋友說難,我想是因為你沒有認真輕言放棄啊,加油啊!今天我練習了半天emacs的快速指南,大家也記得經常去練習哦!一起努力寫出程序來哦!(還有我想聲明一下:本博客只是為了加強自己的專注力,和對比我晚學2天C語言的朋友們提供一些學習上的參考,對有些所謂的“大牛”對我的諷刺,比如說我什麼嘩眾取寵!之類的言語,你趁早關掉你的浏覽器!你只是1個比我先學習幾年或者幾十年的1個人。真正的大牛是像牛一樣辛勤的工作,吃的草,出的是奶。)(從今天到永遠我寫的代碼都將不符合C標准,大家請注意改正過來!)
指針與數組
數組既然也占有存儲單元,所以它也有自己的內存地址,有了內存地址呢,我們的指針變量當然也可以指向數組,也可以指向數組元素啦!既然占內存,必然就有對應的指針啦!
指向數組元素的指針變量
int a[5], *p;
p = &a[0];
1.C語言中,數組名代表數組的首地址,就是第一個元素的地址。因為上面的賦值等價於:p = a;
2.指向數組元素的指針也可以定義時賦值: int *p = &a[0];或者 int *p = a;
引用數組元素
1.int a[5],*p = &a[1] 如果*p = 10; 則表示對p所指向的數組元素a[1]賦值。等價於a[1] = 10;
2.如果p指向一個數組的元素,則p+1表示指向數組該元素的下一個元素。假設p = &a[0],則p+1表示數組元素a[1]的地址。
結論:不管什麼類型的指針+n的時候等價於整型的p+sizeof(type)*n
引用
如果p的初始值是&a[0],那麼:p+i和a+i都可以表示元素a[i]的地址;*(p+i)和*(a+i)都表示指針p+i或a+i所指向的數組元素a[i]的值。
總結:引用一個數組元素可以有兩種方法:下標法:a[i];指針法:*(p+i).
事例:
void main(){ int a[5] = {1,2,3,4,5}; int *p = a; for (int i = 0; i < 5; i++) { printf("%p:%d
", p+i, *(p+i)); }}
輸出結果為:
0012FF34:1 0下標0012FF38:2 地址加了40012FF3C:30012FF40:40012FF44:5
現在如果我們換做數組名可以嗎?我們試試看:
void main(){ int a[5] = {1,2,3,4,5}; int *p = a; for (int i = 0; i < 5; i++) { printf("%p:%d
", a+i, *(a+i)); }}
輸出是:
0012FF34:10012FF38:20012FF3C:30012FF40:40012FF44:5
我們看到完全是可以的。同理我們也可以這樣寫:
void main(){ int a[5] = {1,2,3,4,5}; for (int *p = a; p < a+5; p++) { printf("%p:%d
", p, *p); }}
輸出的結果也是一樣的啦!
但是這裡我們要小心一個錯誤就是:
不要用數組名做++哦!數組名是一個常量!大家一定要記住!
選擇:優先選擇用下標法,因為下標法效率不低於指針法而且下標法更可讀。
指針做減法:請看下面代碼:
大家說,這個程序兩地址做減法後結果為多少啊?!大家可能都認為是4.嘿嘿!其實不是啦!是1.因為兩地址做減法時最後還要除以sizeof(type)哦!
下面我們來看看如何求數組長度:
大家看清楚了嗎?!這樣也可以求出!但是大家記住啊。這裡只是讓我們去理解內存,自己平時寫代碼不要這樣寫哦!
大家來看我們今天的最後1個程序事例啦:
唉!怎麼回事啊!為什麼運行出錯啦!郁悶!這是怎麼回事的啊?!哦!我們仔細看了下,原因是常量區沒有可寫權限呀!
那麼有沒有什麼辦法讓他可以運行啊!其實是可以的啦!只要修改可執行文件的1個標記就可以正常運行啦!我們看看:
我們用二進制方式打開可支持文件:
我們把000228的40改成C0然後保存!再執行可執行文件就可以正常運行啦!我們看改了後:
我們再運行程序輸出為:
szMsg:HelLo, pszMsg:HelLo
szMsg:6, pszMsg:4
嘿嘿!成功運行啦!這是什麼原因呢?!這是因為啊這個40表示可讀不可寫。C0呢表示可讀可寫啦!