中文字幕理论片,69视频免费在线观看,亚洲成人app,国产1级毛片,刘涛最大尺度戏视频,欧美亚洲美女视频,2021韩国美女仙女屋vip视频

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
C語言指針從入門到精通

1. 變量

  1. 不同類型的變量在內(nèi)存中占據(jù)不同的字節(jié)空間。

  2. 內(nèi)存中存儲(chǔ)數(shù)據(jù)的最小基本單位是字節(jié),每一個(gè)字節(jié)都有一個(gè)內(nèi)存地址,這個(gè)地址是一個(gè)十六進(jìn)制的數(shù)。

  3. 聲明一個(gè)變量,在內(nèi)存中是從高字節(jié)向低字節(jié)分配連續(xù)的指定字節(jié)數(shù)的空間。

  4. 任何數(shù)據(jù)在內(nèi)存中都是以其二進(jìn)制的補(bǔ)碼形式存儲(chǔ)的,低位存儲(chǔ)在低字節(jié),高位存儲(chǔ)在高字節(jié)。

  5. 變量的值:存儲(chǔ)在變量中的數(shù)據(jù),叫做變量的值。

  6. 變量的地址:一個(gè)變量是由一個(gè)或者多個(gè)字節(jié)組成的,組成這個(gè)變量的低字節(jié)的地址,就是這個(gè)變量的地址。

  7. 如何取出變量的地址:使用&(取地址運(yùn)算符)運(yùn)算符,&變量名;這個(gè)表達(dá)式的值就是這個(gè)變量的地址。使用%p控制度輸出變量的地址。

  8. 什么是指針:變量的地址叫做指針,指針就是地址,地址就是指針。

下面通過一張圖可以更直觀的理解內(nèi)存中的地址


內(nèi)存中的地址演示圖


2. 指針

  1. 指針是C語言的靈魂。指針變量占據(jù)8個(gè)字節(jié)。

  2. 變量在內(nèi)存中的存儲(chǔ)。
    變量的值:存儲(chǔ)在變量中的數(shù)據(jù),叫做變量的值。
    變量的地址:組成這個(gè)變量的低字節(jié)的地址,就是這個(gè)變量的地址。

  3. 取出變量的地址,用&運(yùn)算符 %p輸出變量的地址。

  4. 變量的地址就叫做指針,我們可以使用一個(gè)指針變量來存儲(chǔ)變量的地址。

指針變量:
  1. 指針變量就是專門用來存儲(chǔ) 地址 的變量,那么我們就說指針變量指向了另外一個(gè)變量,存儲(chǔ)著另外一個(gè)變量的地址。

  2. 指針可以使訪問一個(gè)變量的方式分為兩種
    a. 直接訪問
    b. 可以通過指針變量,找到這個(gè)指針指向的變量
    所以通過指針變量可以間接的訪問指針變量指向的另外一個(gè)變量。

  3. 如何聲明一個(gè)專門用來存儲(chǔ)地址的指針變量
    數(shù)據(jù)類型 
    * 指針變量的名稱 --- int * p1;
    指針變量的名字叫做p1,這個(gè)指針變量的類型是int* 讀作int指針。
    *表示這個(gè)變量不是一個(gè)普通變量,而是一個(gè)專門用來存儲(chǔ)地址的指針變量,所以有哪些普通的數(shù)據(jù)類型,就可以有哪些類型的指針。
    聲明的時(shí)候注意,
    *的位置 建議 int* p這樣提醒我們這是一個(gè)int*類型的指針。
    一個(gè)指針變量并不是可以存儲(chǔ)任意類型的變量的地址,而是有限定的,只能存儲(chǔ)和這個(gè)指針類型相同的普通變量的地址。 所以P 指針變量中只能存儲(chǔ)int類型變量的地址。

  4. 指針變量的初始化 

    int num = 10;int *p =  #
    建議int* p = #這樣寫

    p指針指向了num變量。因?yàn)閜指針的值就是num變量的地址,不能直接賦值一個(gè)非地址類型的常量數(shù)據(jù),也不能直接賦值一個(gè)變量給指針。

  5. p指針自己也有地址, 因?yàn)橹羔樧兞恳彩且粋€(gè)變量,&p取到指針p的地址。

  6. p操作的是p這個(gè)指針變量,可以取p得值,也可以為p賦值

  7. 指針變量的使用
    可以使用指針間接的操作指針指向的變量。
    *p 代表 p 指針指向的變量。
    *p 完全等價(jià)于num 即 *p = 100 完全等價(jià)于 num = 100。
    *p = 100; 表示將100賦值給p指針指向的變量,也就是num變量

    使用指針變量的時(shí)候注意點(diǎn)
    int* p1 ,p2, p3 ; 此時(shí)p1int *指針,而p2,p3int類型數(shù)據(jù) 如果希望全部都是指針需要 int *p1, * p2, * p3;

  8. 野指針
    我們聲明一個(gè)指針變量,如果沒有為其初始化,那么這個(gè)時(shí)候這個(gè)指針變量中是有值的,是垃圾值,隨機(jī)數(shù)。因?yàn)檫@個(gè)時(shí)候,這個(gè)指針變量有可能指向了一塊隨機(jī)的空間,這個(gè)空間可能無人使用,也可能別的程序在用,也可能系統(tǒng)在用,這個(gè)時(shí)候,去訪問指針指向的的變量的時(shí)候,就會(huì)報(bào)錯(cuò)。BAD_ACCESS壞地址訪問錯(cuò)誤,像這樣的指針我們就叫做野指針。

  9. NULL值 完全等價(jià)于0
    為了防止野指針的產(chǎn)生,建議聲明一個(gè)指針變量后,最好為其初始化,如果沒有變量的地址初始化給這個(gè)指針變量。那么就初始化一個(gè)NULL值。NULL值代表指針變量不指向內(nèi)存中的任何地址,這樣就不會(huì)出現(xiàn)野指針,NULL完全等價(jià)于0,所以也可以直接賦值給一個(gè)指針變量0。
    如果一個(gè)指針變量的值是NULL,那么去訪問這個(gè)指針指向的變量的時(shí)候一定會(huì)報(bào)錯(cuò)。

  10. 多個(gè)指針指向同一個(gè)變量,修改其中一個(gè)所有指針指向的值都會(huì)改變。因?yàn)槎鄠€(gè)個(gè)指針指向的是同一塊地址。即 * 會(huì)使指針間接的操作指針指向的變量。

  11. 指針作為函數(shù)的參數(shù)
    如果函數(shù)的參數(shù)是一個(gè)指針,那么就必須要為這個(gè)指針傳遞一個(gè)和指針類型相同的普通變量的地址,這個(gè)時(shí)候,在函數(shù)的內(nèi)部去訪問參數(shù)指針的變量的時(shí)候,其實(shí)訪問的就是實(shí)參變量

  12. 指針作為函數(shù)的參數(shù),可以實(shí)現(xiàn)什么效果?
    函數(shù)的內(nèi)部可以修改實(shí)參變量的值。那么什么時(shí)候使用指針作為參數(shù)呢?
    一般函數(shù)只能返回一個(gè)數(shù)據(jù),那么當(dāng)函數(shù)需要返回多個(gè)數(shù)據(jù)的時(shí)候就可以使用指針作為參數(shù),讓調(diào)用者將自己的變量的地址傳遞給函數(shù)內(nèi)部,函數(shù)內(nèi)部通過指針就可以修改參數(shù),函數(shù)無需將數(shù)值傳回來,就已經(jīng)修改了參數(shù)的值。其實(shí)scanf函數(shù)傳遞的就是指針,因此當(dāng)函數(shù)需要多個(gè)返回值的時(shí)候就可以使用指針作為參數(shù)。

    // 從下面代碼中就可以看出,
    我們可以直接在函數(shù)中修改兩個(gè)變量的值。
    相當(dāng)于函數(shù)有兩個(gè)返回值。
    void  changeValue (int* p1 ,int* p2)
    {    *p1 = 100;    *p2 = 200;}
    int main(int argc, const char * argv[])
    {
       int num1 = 1;int num2 = 2;    changeValue(&num1, &num2);
       printf('num1 = %d\n',num1);
       printf('num2 = %d',num2);return 0;}
  13. 指針為什么要分類型
    指針變量既然是一個(gè)變量就要在內(nèi)存中占用字節(jié)空間
    指針變量在內(nèi)存中占據(jù)多少字節(jié)數(shù)?
    無論指針是什么類型在內(nèi)存中都是占據(jù)8個(gè)字節(jié)。
    那為什么指針還要分類呢?
    p指針變量中存儲(chǔ)的是num變量的地址,也就是num變量低字節(jié)的地址,通過p指針只能找到這個(gè)地址的字節(jié),這個(gè)時(shí)候,通過p指針找到這個(gè)字節(jié),操作的時(shí)候,操作多少個(gè)字節(jié)是則是根據(jù)指針的類型來決定的。
    所以指針變量的類型決定了通過這個(gè)指針找到字節(jié)以后,連續(xù)操作多少個(gè)字節(jié)空間。
    int 指針 連續(xù)操作4個(gè)字節(jié)空間
    double 指針 連續(xù)操作8個(gè)字節(jié)空間
    float 指針 連續(xù)操作4個(gè)字節(jié)空間
    char 指針 連續(xù)操作1個(gè)字節(jié)空間
    因此,指針的類型如果不和指向的變量的類型相同的話,那么通過指針就無法正確的操作指向的變量,所以,指針的變量一定要指向一個(gè)和自己類型相同的普通變量才可以。


    指針為什么要分類型?


  14. 多級(jí)指針
    一個(gè)指針變量中存儲(chǔ)的是一個(gè)一級(jí)指針的地址,那么它就是二級(jí)指針,一個(gè)指針變量中存儲(chǔ)的是一個(gè)二級(jí)指針的地址,那么它就是三級(jí)指針。
    二級(jí)指針:數(shù)據(jù)類型 ** 指針名
    二級(jí)指針只能存儲(chǔ)一級(jí)指針變量的地址。
    多級(jí)指針在開發(fā)中很少用到,遇到多級(jí)指針耐心分析一定可以理清其中的關(guān)系。

  15. 指針與整數(shù)的加減法
    指針可以和整數(shù)進(jìn)行加減運(yùn)算,指針+1并不是在指針地址的基礎(chǔ)之上加一個(gè)字節(jié)的地址,而是在這個(gè)指針地址的基礎(chǔ)之上加一個(gè)單位變量占用的字節(jié)數(shù),例如:如果指針類型是int *則+1代表加4個(gè)字節(jié)地址,以此類推。

  16. 指針與數(shù)組
    我們可以使用指針來遍歷數(shù)組,因?yàn)閿?shù)組的本質(zhì)其實(shí)就是指針,當(dāng)我們創(chuàng)建數(shù)組的時(shí)候,系統(tǒng)會(huì)在內(nèi)存中由高地址向低地址分配連續(xù)的類型所占的空間字節(jié)數(shù) * 數(shù)組內(nèi)元素的個(gè)數(shù)的字節(jié)控件。而數(shù)組名則代表了數(shù)組的低字節(jié)地址,也就是數(shù)組的地址。
    1). 使用指針遍歷數(shù)組的第一種方式.

    //在內(nèi)存中高地址向低地址分配連續(xù)的類型
    所占的空間字節(jié)數(shù)據(jù)*數(shù)組內(nèi)元素的個(gè)數(shù)7*4=28

    int arr[7] = {10,20,30,40,50,60,70};
    //p1指針指向了數(shù)組的第0個(gè)元素
    int* p1 = arr; for(int i = 0; i <>7; i++) {    printf('%d\n',*(p1+i)); }

    2). 使用指針遍歷數(shù)組的第二種方式.

    int arr[7] = {10,20,30,40,50,60,70}; for(int i = 0; i <>7; i++) {    printf('%d\n',*(arr+i)); }

    3). 使用指針遍歷數(shù)組的第三種方式.

    int arr[7] = {10,20,30,40,50,60,70}; int* p1 = arr; for(int i = 0; i <>7; i++) {    printf('%d\n',*(p1++)); } 注意的地方,每次循環(huán),p1的值都會(huì)變化。 最后1次執(zhí)行完畢之后,p1指針指向數(shù)組外面去了,
    p1就不再執(zhí)行數(shù)組中的任何元素了。

    注意: 數(shù)組名代表數(shù)組的地址,而數(shù)組一旦創(chuàng)建,數(shù)組的地址就確定了,不能改變。
    所以,我們不能為數(shù)組名賦值也不能修改數(shù)組名的值,但是可以使用數(shù)組名的值。
    arr是數(shù)組的地址,也是數(shù)組中第0個(gè)元素的地址,arr+1就是數(shù)組中第一個(gè)元素的地址,數(shù)據(jù)名就是一個(gè)地址常量,無法改變。

  17. 數(shù)組作為函數(shù)的參數(shù)的本質(zhì)
    當(dāng)數(shù)組作為函數(shù)的參數(shù)的時(shí)候,在聲明這個(gè)參數(shù)數(shù)組的時(shí)候,并不是去創(chuàng)建一個(gè)數(shù)組,而是去創(chuàng)建一個(gè)用來存儲(chǔ)地址的指針變量,如果我們?yōu)楹瘮?shù)寫了一個(gè)數(shù)組作為參數(shù),其實(shí)編譯器在編譯的時(shí)候,已經(jīng)把這個(gè)數(shù)組變成了指針,這也就是為什么我們通過sizeof計(jì)算參數(shù)數(shù)組得到的永遠(yuǎn)都是8,所以以后我們的函數(shù)如果帶了一個(gè)數(shù)組參數(shù),建議直接寫一個(gè)指向數(shù)組的第0個(gè)元素的指針,在傳入數(shù)組的長(zhǎng)度

  18. 索引的本質(zhì)
    指針變量后面可以使用中括號(hào),在中括弧中寫上下標(biāo)來訪問數(shù)據(jù)。
    p[n];前提p是一個(gè)指針變量,完全等價(jià)于*(p + n);
    所以arr[0] 就等價(jià)于 * [arr + 0]
    操作數(shù)組我們雖然使用中括弧下標(biāo)來操作,實(shí)際上內(nèi)部本質(zhì)仍然是使用的指針來操作。

  19. 存儲(chǔ)指針的數(shù)組
    如果一個(gè)數(shù)組是用來存儲(chǔ)指針類型的數(shù)據(jù)的話,那么這個(gè)數(shù)組就叫做存儲(chǔ)指針的數(shù)組
    格式 :元素類型 數(shù)組名[數(shù)組長(zhǎng)度]; int * arr[3];
    arr數(shù)組里面存儲(chǔ)int指針數(shù)據(jù),最多存儲(chǔ)3個(gè)。

  20. 指針與指針之間的減法運(yùn)算
    指針與指針之間可以做減法運(yùn)算,結(jié)果是一個(gè)long類型的數(shù)據(jù),
    結(jié)果的意義代表兩個(gè)指針指向的變量之間相差多少個(gè)單位變量,絕大多數(shù)情況下,我們用在判斷數(shù)組的兩個(gè)元素之間相差多少個(gè)元素
    如果參與減法運(yùn)算的兩個(gè)指針不指向同一個(gè)數(shù)組,結(jié)果就會(huì)出現(xiàn)問題
    結(jié)果 = 兩個(gè)指針的差 / 每一個(gè)指針變量對(duì)應(yīng)的普通變量占用的字節(jié)數(shù)。
    并且只能做減法運(yùn)算,用在數(shù)組當(dāng)中判斷兩個(gè)元素之間相差多少個(gè)元素。

  21. 指針與指針在之間的比較運(yùn)算 <,><=,>, >=, ==, !=都可以使用
    可以用來判斷兩個(gè)指針指向的變量的字節(jié),誰在高字節(jié),誰在低字節(jié)?;蛘邇蓚€(gè)指針的地址是不是同一個(gè)地址。

  22. 指針和字符變量
    char *name = 'jack';表示直接將一個(gè)字符串?dāng)?shù)據(jù)初始化給一個(gè)字符指針。

    字符指針存儲(chǔ)和字符數(shù)組存儲(chǔ)的區(qū)別

    // 字符數(shù)組存儲(chǔ):
      將字符串?dāng)?shù)據(jù)的每個(gè)字符存儲(chǔ)到字符數(shù)組的元素中,
      并追加一個(gè) \n 表示結(jié)束
      //直接為字符指針初始化一個(gè)字符串?dāng)?shù)據(jù)
     
    char name[5] = 'jack';
     
    char *name = 'jack';

    1.) 當(dāng)他們都是局部變量的時(shí)候
    字符數(shù)組是申請(qǐng)?jiān)跅^(qū)的,字符串的每一個(gè)字符存儲(chǔ)在字符數(shù)組的每一個(gè)元素中。
    指針變量是聲明在棧區(qū)的。但是此時(shí)字符串?dāng)?shù)據(jù)是以字符數(shù)組的形式存儲(chǔ)在常量區(qū)的。此時(shí)指針變量中存儲(chǔ)的是字符串在常量區(qū)的地址。

    2.) 當(dāng)他們作為全局變量的時(shí)候
    字符數(shù)組是存儲(chǔ)在常量區(qū)的,字符串的每一個(gè)字符存儲(chǔ)在這個(gè)數(shù)組中的每一個(gè)元素中。
    字符指針也是存儲(chǔ)在常量區(qū),字符串也是以字符數(shù)組的形式存儲(chǔ)在常量區(qū),指針中存儲(chǔ)的是字符串在常量區(qū)的地址。

    以字符數(shù)組存儲(chǔ)的字符串?dāng)?shù)據(jù),可以修改字符數(shù)組的元素??勺?/p>

  23. 以字符指針的形式存儲(chǔ)字符串?dāng)?shù)據(jù),這個(gè)時(shí)候字符指針指向的字符串?dāng)?shù)據(jù)是無法修改的,不可變

  24. 字符串的恒定型
    前提:以字符指針形式存儲(chǔ)的字符串
    1.) 當(dāng)我們以字符指針的形式存儲(chǔ)字符串的時(shí)候,無論如何,字符串?dāng)?shù)據(jù)是存儲(chǔ)在常量區(qū)的,并且,一旦存儲(chǔ)到常量去中去,這個(gè)字符串?dāng)?shù)據(jù)就無法更改。

    2.) 當(dāng)我們以字符指針的形式要將字符串?dāng)?shù)據(jù)存儲(chǔ)到常量區(qū)的時(shí)候,并不是直接將字符串存儲(chǔ)到常量區(qū),而是先檢查常量區(qū)中是否有相同內(nèi)容的字符串,如果有,直接將這個(gè)字符串的地址拿過來返回,如果沒有,才會(huì)將這個(gè)字符串?dāng)?shù)據(jù)存儲(chǔ)到常量區(qū)中。

    3.) 當(dāng)我們重新為字符指針初始化一個(gè)字符串的時(shí)候,并不是修改原來的字符串,因?yàn)樵瓉淼淖址當(dāng)?shù)據(jù)是不可更改的,而是重新的創(chuàng)建了一個(gè)字符串,把這個(gè)新的字符串的地址賦給他。建議使用字符指針來存儲(chǔ)字符串?dāng)?shù)據(jù)。優(yōu)勢(shì):長(zhǎng)度任意。

    //這樣可以 但是并不是把jack改成了rose,
    而是重新創(chuàng)建一個(gè)'rose'把rose地址賦值給name

    char *name = 'jack';nsme = 'rose';
  25. 字符串?dāng)?shù)組
    char *names[4] = {'aa','bb','cc','dd'};
    names數(shù)組的元素的類型是char指針,初始化給元素的字符串?dāng)?shù)據(jù)是存儲(chǔ)在常量區(qū)的。元素中存儲(chǔ)的是字符串在常量區(qū)的地址。
    因此這是一個(gè)存儲(chǔ)指針的數(shù)組,每一個(gè)元素的類型是一個(gè)指針,占用得內(nèi)存為8個(gè)字節(jié)。

  26. 指向函數(shù)的指針
    程序在運(yùn)行的時(shí)候,會(huì)將程序加載到內(nèi)存,內(nèi)存的代碼段中主要存儲(chǔ)的就是程序的代碼,而程序的代碼就包括函數(shù)。既然函數(shù)要存儲(chǔ)在內(nèi)存中,那么肯定要用1塊空間來存儲(chǔ),那么這個(gè)塊空間一定有1個(gè)地址。
    因此我們就可以聲明1個(gè)指針用來存儲(chǔ)這個(gè)函數(shù)的地址,也就是說讓這個(gè)指針指向這個(gè)函數(shù)。這樣我們就可以使用指針來間接的調(diào)用函數(shù)。
    優(yōu)勢(shì): 調(diào)用函數(shù)有了兩種方式。
    1.) 直接使用函數(shù)名調(diào)用
    2.) 使用指向函數(shù)的指針間接調(diào)用.

  27. 指向函數(shù)的指針的聲明
    一個(gè)指向函數(shù)的指針,并不是任意的函數(shù)都可以指向,而是有限定的,要求指向的函數(shù)的返回值類型和參數(shù)描述必須要與指針的描述一樣。

    聲明語法

    返回值類型
    (*指針名)([參數(shù)列表]);
    //
    表示聲明1個(gè)指向函數(shù)指針,叫做pFunction
    //這個(gè)指針只能指向沒有返回值,并且沒有參數(shù)的函數(shù)
    void (*pFunction)();
    //表示聲明了1個(gè)指向函數(shù)的指針,叫
    pFun,
    這個(gè)指針只能指向返回值為int類型,
    并且有兩個(gè)整型的參數(shù)的函數(shù)
    int(*pFun)(int num1,int num2)
  28. 指向函數(shù)的指針的初始化

    函數(shù)的名稱就代表函數(shù)的地址,因此我們直接將符合條件的函數(shù)的名稱賦值給這個(gè)指針。
    并且我們有兩種方法可以通過指針來調(diào)用這個(gè)函數(shù)。

    int MaxValue (int a, int b)
    {  
       return a > b ? a : b;}
    int main(int argc, const char * argv[])
    {  
     
    // 創(chuàng)建一個(gè)返回int 并且有兩個(gè)int型參數(shù)的函數(shù)指針,并賦值   int(*pMaxValue)(int a, int b) = MaxValue;
     
     
    //通過指針調(diào)用函數(shù)方法1   printf('%d\n', pMaxValue(5,10));

     
    //通過指針調(diào)用函數(shù)方法2   printf('%d\n',(*pMaxValue)(6,9));

     
    //調(diào)用函數(shù)   printf('%d\n',MaxValue(9, 13));

     
    //輸出函數(shù)的地址return 0;   printf('%p\n',MaxValue);}


本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
『C程序設(shè)計(jì)』讀書筆記
數(shù)組結(jié)構(gòu)體總結(jié)
【C語言】C語言基礎(chǔ)知識(shí)概念
深入理解C語言
“C/C 中char* 和 char「」區(qū)別
C 語言程序設(shè)計(jì)---指針
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服