日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言指针(基础篇)

發布時間:2024/1/1 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言指针(基础篇) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 前言
  • 一、指針與地址
    • 1. 變量與內存
    • 2. 地址與指針
    • 3. 常量、變量、內存、地址、指針的關系
  • 二、指針的基礎操作
    • 1.大端模式與小端模式
    • 2. 指針的定義與初始化
      • 2.1 指針的定義與初始化
      • 2.2 一個例子
      • 2.3 指針的定義與初始化舉例及圖示
    • 3. 指針的運算
    • 4. 示例演示
  • 三、二級指針

前言

??????指針是C語言的靈魂,C語言因為指針而在眾多語言中所向披靡,也使得C語言一直盛行到現在。因為指針的存在也使得C語言的可操作性極大提升,學好指針是十分必要的,下面將為大家來細致的講解C語言中指針的知識點也是一些易混易錯知識點。

一、指針與地址

1. 變量與內存

??????C語言定義變量我想大家都很熟悉了,假如說我想定義一個整型變量 a 。

int a;

??????其實要明確的一點是,我們在C語言中只要是定義的變量它都是存儲在內存中的,不管是普通變量,結構體變量還是指針變量,都是存儲在內存中的。在32位操作系統中,一個程序的內存有4G。當然這里所指的內存是虛擬內存。

2. 地址與指針

?????? 在C語言中每塊內存都是以字節為單位,每個內存都有一個編號,每一個編號都是以32位二進制數表示, 我們把這個編號就稱之為地址,如下圖所示。并且通過下圖我們能夠確定,每個地址的值都是唯一的。那么指針是用來干嘛的呢?其實指針就是用來存儲地址的。

?????? 其實通過上面的信息我們能夠驗算兩個問題。
問題一: 為什么32位操作系統中,指針都是4字節?
??????因為指針存儲的是地址,而地址是一個32位二進制數,一個字節是8位二進制數,所以 32 / 8 = 4(字節)。
問題二: 為什么32位操作系統中,虛擬內存是4GB?
??????因為每塊內存的1字節,每個內存編號是32位二進制數表示,所以內存一共有 2^32 字節大小,換算下單位 2^32(Byte) = 4,294,967,296(Byte) = 4,194,304(KB) = 4,096(MB) = 4(GB)。

3. 常量、變量、內存、地址、指針的關系

?????? 常量是存儲在變量中,變量是存儲在內存中的,每個內存都有一個編號,我們稱這個編號為地址,指針就是用來存儲地址的。 這句話大家一定要牢記。

??????站在編譯器的角度,假如定義一個字符類型的變量a,并對其賦值為10,其實編譯器就會在內存中分配出一塊內存,假如這塊內存的地址是 0x12345678 ,那么這塊內存里面存儲的數值就是10, 同時這塊內存就叫做a,通過 a 我們就能讀取到內存里面存儲的內容,通過取地址符&,我們就能得到這塊內存的地址或者也可以說變量的地址,即 &a 的值為 0x12345678 。

二、指針的基礎操作

1.大端模式與小端模式

??????在介紹指針之前,需要先介紹以下大端模式和小端模式,大端模式和小端模式其實就是數據的存儲方式不一樣。像ARM,摩托羅拉,MIPS等采用的是大端模式的存儲方式,像Intel等采用的就是小端模式。
大端模式:高地址存儲數據的低位,低地址存儲數據的高位。
小端模式:高地址存儲數據的高位,低地址存儲數據的低位。

??????圖解如上,假如變量a的地址是0x000000a1,那么對于大端模式,地址0x000000a1存儲的是數值0x12;對于小端模式,地址0x000000a1存儲的是數值0x78。

2. 指針的定義與初始化

2.1 指針的定義與初始化

指針的定義:

<存儲類型> <數據類型> *<變量名>

指針的初始化:

1.先定義,后初始化 <存儲類型> <數據類型> *<變量名>; <變量名> = <地址>;2.在定義時初始化 <存儲類型> <數據類型> *<變量名> = <地址>;
  • 存儲類型:C語言的存儲類型有4中,分別為 auto、static、 register、 extern。在一般情況下我們通常會對存儲類型進行省略不寫,但其實省略不寫,就相當于存儲類型就是 auto。
  • 數據類型:數據類型就是C語言的基本數據類型,像 int 、char、float 等等。
  • *號記得一定要寫,*號和后面變量名結合,代表該變量名是一個指針變量。
  • 變量名:符合C語言標識符命名規格即可。
  • 2.2 一個例子

    int a = 10;
    int *p = a;

    p是一個指針變量,它里面存儲的是一個地址。
    *p在定義時是表示p是一個指針變量,在后面的運算中*p是一個值,存儲的一個地址。
    &p是一個常量,表示p所占用的內存地址。

    2.3 指針的定義與初始化舉例及圖示

    源代碼:

    #include <stdio.h>int main() {/*a是指針變量,b是int型變量*//*a被定義時未初始化,此時a是野指針,a里面存儲的值是編譯器隨機分配的,直接使用野指針會造成代碼的不確定性*/int *a, b; /*將指針變量a指向b的地址*/a = &b;/*對變量b的內存里面的內容寫成10*/b = 10;/*取出指針變量里面的內容用取值運算符*號*//*除了在定義時的*號+變量表示該變量是一個指針以外,在之后遇到的*號+變量都是表明是取出指針變量里面的內容的*//*因為a是一個地址,所以用%p打印,又因為*a是一個值,是表示取出a中存儲的地址的值,所以用%d打印*/printf("&a = %p, a = %p, *a = %d, &b = %p, b = %d\n", &a, a, *a, &b, b);return 0; }

    運行結果:

    &a = 0061FE18, a = 0061FE14, *a = 10, &b = 0061FE14, b = 10

    圖示:

    ?????? 如圖所示,定義變量 b 的內容是10,b 的地址是 0x0061FE14,a 存儲的是 b 的地址,所以 a 內存里面的內容就是b的地址值,所以 a 里面存儲的數值為0x0061FE14,通過取值運算符,*a 表示的是取出a中存儲的地址里面的內容,a中存儲的地址是0x0061FE14,地址0x0061FE14中存儲的值是 10,所以 *a 的值是10。

    3. 指針的運算

    ?????? 指針的運算其實本質上就是地址的運算。
    例如:

    char *a; short *b; int *c;
  • 算術運算:指針的算數運算的偏移是指針指向的類型的大小的偏移。
    如 +、-、++、-- 運算
    (1)a 是 char* 類型,說明指針變量 a 是指向字符變量 char , char占一個字節,所以 a+1 的地址指向a后面的第一塊內存,假如 a 原本指向的地址是 0x00000010, 那么 a+1 指向的地址是 0x00000011,a-1 指向的地址是 0x0000000f。
    (2)b是 short* 類型,說明指針變量 b 是指向短整型變量 short , short占兩個字節,所以 b+1 的地址指向b后面的第二塊內存,假如b原本指向的地址是 0x00000010, 那么 b+1 指向的地址是 0x00000012,b-1 指向的地址是 0x0000000e。
    (2)c是 int* 類型,說明指針變量 c 是指向整型變量 int, int占四個字節,所以 c+1 的地址指向c后面的第四塊內存,假如c原本指向的地址是 0x00000010, 那么 c+1 指向的地址是 0x00000014,c-1 指向的地址是 0x0000000c。
  • 關系運算:(如 >、<、>=、<=、==、!=)
    比如定義兩個整型指針變量 int *a, *b; 假如 a > b 說明 a 的內存中存放的地址比 b 的內存中存放的地址值要大。雖然不同類型的指針變量也可以比較大小,但沒有實際意義。
  • 賦值運算:(如 =、+=、-=)
    比如定義一個 int *a; 后續不管對指針變量 a 賦值成什么,在 a 看來這個值就是一個地址,通過 *a 可以得到 a 中存儲的地址中的內容。
  • 4. 示例演示

    源代碼:

    #include <stdio.h>int main() {char a = 10;int b = 20;char *pa = &a;int *pb = &b;/*通過修改指針間接修改變量a的內容,通過修改變量,指針獲取的值也會發生變化*/*pa = 11;b = 22;/* *(&b)通過地址運算符先取出b的內存地址,然后通過取值運算符取出地址里面的值,也就是 *(&b) 和 b 這兩種取值的方式是完全等價的*/printf("a = %d, *pb = %d, *(&b) = %d\n", a, *pb, *(&b));/*將字符指針指向整型變量*//*22的二進制數是0x00000016, 如果打印結果是0x16,那么該機器是小端模式,如果打印結果是0x00,那么該機器是大端模式*/pa = &b;printf("*pa = %#x\n", *pa);return 0; }

    運行結果:

    a = 11, *pb = 22, *(&b) = 22 *pa = 0x16

    三、二級指針

    ?????? 我們知道一級指針是用來存儲變量的地址的,那么一級指針變量其實也是個變量,那么它同樣的也應該有他的地址,==存儲普通變量地址的變量我們稱之為一級指針變量,存儲一級指針變量地址的變量我們就稱之為二級指針變量。==依此類推,存儲二級指針變量地址的變量我們就稱之為三級指針變量… ,盡管如此,但我們平時用到最多的還是一級指針和二級指針,更高級的指針在工作中用得可以說是很少了,并且,更高級的指針也使得代碼的可讀性變低,所以我們就不需要對其討論,并且當掌握了二級指針,后面更高級別的指針都是以此類推的。
    ?????? 其實二級指針的一些屬性和一級指針基本差不多,我們直接通過一個實例來對其進行講解,講解都在代碼中。
    源代碼:

    #include <stdio.h>int main() {int a = 10;/*pa是一級指針變量,&pa是取出一級指針變量的地址,一級指針變量的地址要二級指針來存儲*/int *pa = &a;/*定義二級指針變量ppa, 用來存儲二級一級指針變量的地址*/int **ppa = &pa;/**ppa 和 pa 是等效的,**ppa 和 *pa 是等效的,又因為 *pa 和 a 是等效的,所以 **ppa, *pa, a 是等效的1. &ppa 是二級指針變量的地址,需要用三級指針來存儲。2. ppa 是存儲了一級指針變量的地址,ppa 等價于 &pa, 所以 ppa是一個地址。3. *ppa 是一級指針變量里面的內容,一級指針變量里面的內容是普通變量的地址,所以 *ppa 和 pa 等價,所以 *ppa 也是一個地址4. **ppa 是一個值。*/printf("&ppa = %p, ppa = %p, *ppa = %p, **ppa = %d, &pa = %p, pa = %p, *pa = %d, &a = %p, a = %d\n", &ppa, ppa, *ppa, **ppa, &pa, pa, *pa, &a, a);return 0; }

    運行結果:

    &ppa = 0xbfc496ac, ppa = 0xbfc496a8, *ppa = 0xbfc496a4, **ppa = 10, &pa = 0xbfc496a8, pa = 0xbfc496a4, *pa = 10, &a = 0xbfc496a4, a = 10

    圖示:

    總結

    以上是生活随笔為你收集整理的C语言指针(基础篇)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。