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.在定義時初始化 <存儲類型> <數據類型> *<變量名> = <地址>;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. 指針的運算
?????? 指針的運算其實本質上就是地址的運算。
例如:
如 +、-、++、-- 運算
(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三、二級指針
?????? 我們知道一級指針是用來存儲變量的地址的,那么一級指針變量其實也是個變量,那么它同樣的也應該有他的地址,==存儲普通變量地址的變量我們稱之為一級指針變量,存儲一級指針變量地址的變量我們就稱之為二級指針變量。==依此類推,存儲二級指針變量地址的變量我們就稱之為三級指針變量… ,盡管如此,但我們平時用到最多的還是一級指針和二級指針,更高級的指針在工作中用得可以說是很少了,并且,更高級的指針也使得代碼的可讀性變低,所以我們就不需要對其討論,并且當掌握了二級指針,后面更高級別的指針都是以此類推的。
?????? 其實二級指針的一些屬性和一級指針基本差不多,我們直接通過一個實例來對其進行講解,講解都在代碼中。
源代碼:
運行結果:
&ppa = 0xbfc496ac, ppa = 0xbfc496a8, *ppa = 0xbfc496a4, **ppa = 10, &pa = 0xbfc496a8, pa = 0xbfc496a4, *pa = 10, &a = 0xbfc496a4, a = 10圖示:
總結
以上是生活随笔為你收集整理的C语言指针(基础篇)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 绘制三线表
- 下一篇: 软考 信息系统管理工程师和系统集成项目管