最近在忙著春招。許多知識點都開始複習,c++的知識點都忘的差不多了,尤其是一直迷迷糊糊的指標,昨天剛剛學完一波兒,現奉上原創部落格的位址。在本篇文章中,還有我個人的部分感想和操作,一起奉上。
c++或者c裡面最容易讓人糊塗應該是指標了,不管是初學者甚至是有經驗的童鞋有時候在用指標的時候也會出現一些很隱蔽的錯誤.
指標本身就是乙個很繞的概念,而指標又能夠和很多的結構比如陣列(二維陣列),字串,記憶體分配和管理等等一些聯絡起來變成更加繞的概念.所以基礎不好的同學常常會犯一些很無厘頭的錯誤,但是高手也會犯錯誤,而且更加隱蔽.
接下來所有的文章內容並不能夠保證你能夠完完全全避免開發中的錯誤,但是文章的目標是幫助很多童鞋對於指標概念做乙個系統性的歸納.減少犯錯誤的機率.或者是幫助剛剛入門的boy更加快速深入的理解指標,把基礎打得紮實一點.
恩,很多人都說指標很難,那為什麼還要學指標呢?對於這樣的問題,拒絕回答.
我們已經很熟悉一些基本的儲存單位了,比如乙個bit(位)用儲存0或者1.也可以把幾個bit合起來表示更大的數字,比如乙個byte(位元組)就包含了8個bit.這些都是很基礎很簡單的東西.然後我們可以把計算機的記憶體想象成乙個位元組陣列,記憶體中的每乙個位址表示乙個位元組.
每個位元組中都能夠儲存一定位數的內容,因此,每個位元組都能夠通過一些位址來標識.有時候,乙個位元組不夠,怎麼辦呢?那麼就同時用很多個位元組來表示,比如乙個int在我的系統裡面就用了4個位元組。
下面的圖是上面那幅每兩個位元組合併在一起之後樣子.這個因為是兩個位元組合併,所以它成為比乙個位元組更大的記憶體單位(廢話),能夠儲存的資訊就更多(廢話).但是雖然乙個字是兩個位元組合併的,但是它仍然只包含乙個位址,也就是說,合併之後只需要乙個位址來找到合併之後的記憶體.
因此,我們可以得到:
1.記憶體中的每個位置都由乙個獨一無二的位址表示.
2.記憶體中的每個位置都包含乙個值.
通俗一點,我們可以通過乙個位址,來找到記憶體中的某個具體位置,然後訪問到(得到)該位置的值(允許的話).這就是記憶體和位址簡單的思想.
指標這個名字確實折磨過很多人,這個名字是個好名字,同時也是乙個非常不好的名字. 說它好,是因為指標這個東西很形象的體現了它的功能:指標指標,指到某個地方某個位置.非常形象. 它不是個好名字是因為她的名字有時候掩蓋了它的真實含義.一般來說,指標是乙個其值為位址的變數。(就是乙個儲存位址的變數)
所以,要養成一種條件反射,看到指標首先不是想到他能夠指向**,而是想到這個變數存放的是乙個位址,是這個位址指向****.(比如,char型別的變數中存放的是char型別的資料.int變數中存放的是int型別的資料.指標中存放的是乙個位址!!!)
反覆的把上面的概念消化之後,我們就來看兩個基本的運算子:&(取址運算子)和*(間接訪問運算子/解引用指標)
首先是&運算子:當它後面跟乙個變數名的時候,給出這個變數名的位址.
#include
using
namespace
std;int
main()
int main()
這是我的做法,希望能對你有幫助。
使用指標的方式有很多,我們這裡談談最基礎的,後面會更加深入的講指標的使用.前面已經講過了指標的建立,接下來主要是講指標的初始化問題和賦值以及解除引用等等問題.
首先是初始化問題.在前面的那乙個例子中,我們在建立指標的時候都順便初始化了,那是不是建立指標就一定要初始化?肯定不是!建立指標的時候也可以不初始化.因為有時候你建立乙個指標只是為了後續的工作,根本沒有東西拿來初始化.那麼到現在,我們解決了第乙個問題,那就是建立指標可以初始化也可以不初始化,.那麼你肯定會說,這麼簡單為什麼要單獨拿出來講?是因為後來的某些操作是要考慮是否初始化的問題的.好了,不繞彎了,這裡的操作主要是講間接訪問(解引用指標)帶來的一些問題.不多說,直接上例子.
#include
using
namespace
std;int
main()
例子很簡單,就不解釋了.
有乙個非常重要的是,因為null不指向任何地方,所以,也就肯定不能夠解引用了.這點一定要注意.因為連位址都沒有,怎麼得到不存在的位址中的值呢?所以要是想你的程式健壯,最好是在解引用之前加乙個判斷是否為null指標的步驟,要是你有足夠的信心以後都不會有問題,那麼不加也罷.
下面這個例子是當我試圖對乙個null指標解引用之後的程式運**況.(就是上面那個例子加了一句話而已)
#include
using
namespace
std;int
main()
int main()
講到現在,發現前面很多的錯誤都是由於解引用沒有初始化的指標引起來的.所以,這裡提個建議,就是盡量定義了物件之後再定義指向這個物件的指標,對於不清楚的指向**的指標,一律初始化為nullptr(c++11)或者null(0).之後再判斷是否指向物件再進行相應的操作.
接下來講void*.
void*
是一種特殊型別的指標,能夠用來存放任何型別物件的位址.通俗來說,就是我不知道這個指標指向的是什麼型別的物件.
要是還是理解不了那就上例子:
void *暫時了解到這裡就行了,後面記憶體分配的時候還會專門和他打交道.
指標的指標就是指向指標的指標.再多講就繞暈了.直接看定義和例子吧.
通過這個例子,我們發現其建立方式也是和普通指標的建立方式是差不多的,除了建立時候的兩個星號**
.那建立指標必定需要指標型別,指標型別怎麼選擇呢?通俗一點說,就是跟著前面的走:我們發現建立整形時候使用的是int
,比如這裡的int a=10;
.那我們建立指向a的指標的時候,肯定必須也要是int了,比如這裡的int *p_a=&a;
.最後建立指標的指標的時候,也就用int了.比如這裡的int **pp_a=&p_a;
.並不困難
另外乙個就是解引用的時候,帶上兩個星號,就回到的最開始的那個變數.這麼說有點模糊.詳細來說,**pp_a
因為*
的從右向左的結合性,這個表示式可以寫成*(*pp_a),
那麼我們知道pp_a
存放的是p_a
的位址,*pp_a
就是表示p_a
這個位址中存放的內容即a的位址(不能暈!!!).那麼*(*pp_a)
就相當於*p_a
或者a.
至此,基本的概念部分就結束啦.
一起來挑戰Google code jam 一
給你兩個陣列va和vb,兩個陣列的元素對應相乘,然後求和,要求和最小,在陣列元素順序可以調整的時候。這裡主要用到乙個不等式,x和y兩個公升序的陣列,那麼sum x i y i sum x i y n i void fun printf d n res 題意是給你一排p個牢房,最初的時候每個牢房中有乙...
一起來學習Ant Design
當然,都屬於webpack中的基礎知識,但是套上了atool build這樣乙個殼子,又有點小懵。還好不是很難,嘗試後,很快搞定了,順手也總結一下吧!一 安裝ant init 1 npm install antd init g 二 建立目錄 1 mkdir antd demo cd antd dem...
一起來存方法
1.在動態渲染元素的時候,需要邏輯判斷 在迴圈渲染dom元素時,迴圈遍歷中需要邏輯操作,如果不使用模板 1 var addlist function 7 if 條件2 10lists.push list 11 12 id html lists.join 13 這是在看一同事 時,發現她用push和j...