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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言 关于指针的格式化

發(fā)布時間:2025/3/20 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言 关于指针的格式化 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
寫這篇文章時由于沒有參考過什么權(quán)威資料教材,所以有些觀點可能是錯誤的, 不過我本人都是經(jīng)過大量調(diào)試后才寫出來的啦..

1. 內(nèi)存由多個單位為8bit = 1byte的單元組成,每1個單元都配有1個編號,這個就是內(nèi)存地址。
?????????? 計算機(jī)的主存儲器是內(nèi)存,而不是硬盤,因為cpu只能直接訪問內(nèi)存...? 而cpu訪問內(nèi)存是根據(jù)內(nèi)存的編號來訪問的,這個編號就是內(nèi)存地址,cpu獲得內(nèi)存地址就能直接尋址到對應(yīng)的內(nèi)存單位。


2.指針就是內(nèi)存地址..它們是同一概念
?????????? 很多人都講指針就是指向內(nèi)存地址的東西, 但是我認(rèn)為指針就是內(nèi)存地址..


3.指針變量的概念
???????????
首先,指針變量是1個變量, 也就是它的值是可以變的。? 其次,指針變量是1個特殊的變量, 它存放的值是1個指針(也就是內(nèi)存地址啦,所以我認(rèn)為它們是同一樣野..


?
4.指針變量所占字節(jié)
????????????
在32位的操作系統(tǒng)中, 系統(tǒng)會使用32個2進(jìn)制位來表示內(nèi)存地址, 就是從0000...(32個0)....00 到1111...(32個1)..111, 在這里面的每1個2進(jìn)制數(shù)的都可以表示1個地址, 那么這里面有多少個地址呢? 就是2的32次方 = 4G 個啊。

???????????? 而每1個地址對于1個大小為1byte=8bit(1字節(jié))的內(nèi)存單元, 所以32位系統(tǒng)最多只支持4GB內(nèi)存的原因就是這個了,因為地址不夠用啊.

???????????? 而每1個地址都要用32個bit(位來表示), 那么如果要存放這個地址在內(nèi)存中, 就必須要有32個bit的位置的內(nèi)存,前面講到了,每個內(nèi)存單位的容量是8bit, 所以需要4個內(nèi)存單元來存放1個內(nèi)存地址(指針), 也就是說1個指針變量需要 4個地址的內(nèi)存來存放. 占4個字節(jié)。
???????????? 即sizeof(p) = 4 了 //p是1個指針
???????????? 即對于32位系統(tǒng)來講, 1個指針變量的長度是4字節(jié)
????????????
通常我們會講2進(jìn)制的地址換算成十六進(jìn)制來表示,
???????????? 就是從0x 00000000? 到0x FFFFFFFF????
???????????? 上面的0x 只不過是十六進(jìn)制的標(biāo)志.


????????????

?????????????在64位的操作系統(tǒng)中,相應(yīng)地系統(tǒng)會用64個2進(jìn)制位來表示1個地址, 理論上會有17億多G個地址, 支持17億GB內(nèi)存...當(dāng)然只是理論上了啊。
?????????????? 所以64位操作系統(tǒng)中, 1個地址需要64bit內(nèi)存來存放, 也就是1個指針變量長度是8byte(字節(jié))啦

?????????????? 由于本屌的系統(tǒng)是64位的, 所以下面的內(nèi)容和例子都是基于64位系統(tǒng)來說明的。

?????????????? 下面是一張內(nèi)存的大概結(jié)構(gòu)圖



?
??????????????????????????

??????????上面都是一些基本概念, 下面開始才是真正想要說的內(nèi)容.?????



?
5.為什么定義指針變量時要同時指定它的類型。
? ? ? ? ?
通常我們定義1個指針時要同時指定指針的類型:
? ? ? ? ? 例如
?????????
char * p; //定義1個char類型的指針 int * p; //定義1個整性指針


? ? ? ? ? 其實,指針的類型決定了指針獲取對應(yīng)地址內(nèi)存單元的后續(xù)單元個數(shù), 怎么理解呢?
? ? ? ? ?
???????? 參考上圖,下面的指針就是1個char 類型的指針,指向了上面的char類型的變量, 地址是00000000FFFF0001,? 而char類型只占1個字節(jié), 所以cpu找到這個地址后就直接獲得char類型的值了( 01100001 的值是97 ascii換算后就是字符'a')

???????? 5.1 int類型變量占4字節(jié), 占用4個地址的內(nèi)存
???????? 但是如果下面的指針要指向上圖藍(lán)色的int類型變量呢?
???????? 可以由圖中得知,int 類型占4個字節(jié)啊, 也就是占住4個地址, 分別是00000000FFFF0002, 00000000FFFF0003,
00000000FFFF0004, 00000000FFFF0005,??? 但是下面char類型指針只能存放1個地址啊?

???????? 如果我們強(qiáng)制把其中1個int類型的賦給char 類型指針, 就很能報錯了, 因為char 類型指針只能訪問1個地址內(nèi)存啊...

???????? 例如我們寫個代碼如下:
??????? int i = 123;char * p;p = &i; // error char類型指針不能指向int類型的變量


????????
?????? 5.2 要指向int類型的變量或常量, 則必須要用int 類型的指針
? ? ? ??
??? 如果要用指針指向那個Int 類型的變量, 就必須定義1個int 類型的指針
?????????????
int i = 123;int * p;p = &i; //正確

?????????????? 那是不是指 int 類型指針的長度是char 類型指針的4倍, 能存放4個地址呢?
? ? ? ? ? ? ?? 當(dāng)然不是, 其實所有類型的指針長度都一樣的, 都只能放1個地址!

? ? ? ? ? ? ? ? 所有當(dāng)執(zhí)行 p =&i; 時,? 系統(tǒng)實際上是把變量i的頭1個字節(jié)的地址 賦值給指針p.
??????????????? 而p去訪問他的存放地址時, 首先就會指向int類型i的頭1個字節(jié), 而因為它是1個int類型的指針, 所以它會頭1個字節(jié)開始, 共訪問 int類型的長度個數(shù)的字節(jié).

???????????
?????????????? 而int 類型的長度是4嘛. 所以p指需要知道 int類型的變量的頭1個地址, 然后從頭1個字節(jié)逐個訪問4個字節(jié)的內(nèi)存, 就能完全取得int類型的值了.
????????????????
??????????????? 如下圖:

???????????????


?????????????
???????????
??? ? ? ? ? ?????????
?6.指針可以和整數(shù)執(zhí)行加減運算
????????? 我們經(jīng)常在代碼看到 p++;? p--; 這種語句. 其中p是1個指針啦.
????????? 那么p+1 到底代表什么呢?
????????? 其實假如 n 是 1個整數(shù)

????????? 那么 p+ n 其實就是另1個指針,? 它 指向P的地址再加上 p指向的數(shù)據(jù)類型(也就是p的指針類型)的長度 乘于 n.

????????? 也就是假如p 是1個char 類型的指針, 它指向的地址是 0000FFFF00000001 , 那么p + 1 就指向 0000FFFF00000002
?????????? 假如p是1個 Int 類型的指針 它的指向的地址是FFFFFFFF00000001, 那么p+1 就指向 FFFFFFFF00000005
???????
?????????? 也就是
???? ? ???? p + n指向的地址 = p指向的地址? + sizeof(p的類型) * n

?????????? 畫個圖:
????????



?????? 假如上面的內(nèi)存存放的是1個int 類型數(shù)組的數(shù)據(jù)P.?? 那么P指向的就是頭1個數(shù)組元素的地址了.
??????? 而數(shù)組的變量名字本身是1個指向第1個數(shù)組元素的指針
??????? 也就是 *p = p[0]
??????? 而p + 1 指向的是下1個元素的地址 即 *(p+1) =? p[1]

??????? 所以就得出經(jīng)典公式? *(p+n) = p[n]


8.
不同的類型的指針可以指向同1個地址.
??????
大家留意上圖, 貌似int 類型 p 和 char 類型的指針q 都指向同1個地址啊..
???????? 寫幾行代碼做個例子.
????
int i = 97;int * p = &i; // 定義1個int 類型指針 指向i的地址int * p2 = &i; //在定義1個指向i的地址的int類型指針 p2, 完全無問題的,只不過浪費8字節(jié)去存放這個指針變量了.現(xiàn)在我想定義1個指向i地址的char 類型指針?char * q = &i; //定義1個指向i的地址的 char 類型指針, // 在linux gcc里是可以通過編譯的, 但是有warning 信息, 不推薦



???????? 那么正確的寫法是什么呢?
???????? 因為i 是1個 int類型變量,?? &i就是 這個變量的首個字節(jié)地址.? 如果要將這個地址傳給1個 char類型的變量.
???????? 就要對其進(jìn)行格式化

???????? 正確寫法:
???????? char * q = (char *)&i; //將int類型變量i的頭部地址格式花成 char類型的地址.

????????
???????? 這個就是指針的格式化了( 內(nèi)存地址格式化)? // 這句話只是我自己的理解, 有可能是錯的!

???????? 那么這樣做有什么效果呢?
???????? char類型指針 q指向 int類型 i后,? *q 是什么????

????????? 見下圖:
????????

?
???????? 因為q指向的地址內(nèi)容是 01100001 ,就是 97的二進(jìn)制表示嘛, 而q是1個char 類型的指針. 所以 *q 就是 97的 ascii對應(yīng)字符 就是小寫字母'a'啊.

???????? 下面寫個例子程序:

?

執(zhí)行結(jié)果:

?

其實 *q 的真實地址內(nèi)容是 01100001 這個8個bit 的二進(jìn)制數(shù).? 作為char類型的值就是'a'了,上面程序第個printf 函數(shù)只是強(qiáng)制輸出為十進(jìn)制數(shù).

附上gdb的調(diào)試信息, 可以看到本例子 p 和 q的指向地址都是 0x7fffffffdebc 啦


?


9.內(nèi)存插入數(shù)據(jù)的規(guī)律.
?????
我們來研究下數(shù)據(jù)是怎樣插入內(nèi)存的.
?????????? 我們知道1個int 類型是占4字節(jié)啦 (講過好多次了)
?????????? 而當(dāng)定義1個i 變量時. 系統(tǒng)就會給它分配 4字節(jié)內(nèi)存.
?????????? 而當(dāng)給i 賦值時, 系統(tǒng)就忘對應(yīng)內(nèi)存寫數(shù)據(jù)了
?????????? 例如 當(dāng)執(zhí)行? i = 97; 時,???????? 系統(tǒng)會將97 換成二進(jìn)制 1100001, 但這只占7個位. 還有前面32 -7 = 25個位就是0了. 所以
?????????? 97 = 00000000 00000000 00000000 01100001

?????????? 問題是這些數(shù)據(jù)怎么插入內(nèi)存呢,? 見上圖debug信息: 內(nèi)存里是
?????????? 01100001
?????????? 00000000
?????????? 00000000
?????????? 00000000

?????????? 點解貌似反了啊. 不是應(yīng)該如下嗎:
?????????? 00000000
?????????? 00000000
?????????? 00000000
?????????? 01100001

??????? 內(nèi)存每1個位(bit) 都有順序. 分高低位.
???????????
到底怎么分呢,
?????????????? 首先,地址小是地位. 地址大的是高位.
?????????????? 相同地址的8個bit中, 按照常識, 左邊是高位.
??????????????
??????????????? 而插入數(shù)據(jù)時,? 是從低位開始寫入地位的內(nèi)存, 一直到高位.
?????????????? 例如97 這個整數(shù),?
??????????????? 00000000? 00000000?? 00000000 01100001
??????????????? 從左到右是高到低,? 插入內(nèi)存時就下圖所示了:

?

????????????? 假如我定義1個int類型變量
???????????? int i = 24930;
?
????????????? 接下來定義1個char 類型指針指向它.
???????????? char *q = &iprintf("*q is %c\n", *q) //*q是多少呢?printf("*(q+1) is %c\n", *(q+1)) //*(q+1) 又是多少呢?


????????????? 步驟還是先把24930 這個化為二進(jìn)制數(shù) 110000101100010, 然后補(bǔ)齊到32bit (4字節(jié))
????????????? 就是 00000000? 00000000 0110000101100010
????????????? 那么p 就是指向最低位(頭部地址)的字節(jié)?? 01100010? ,化成10進(jìn)制數(shù)是98 啊, ascii碼就是小寫字母'b'了
????????????? 而p+1 指向p的地址加上 1乘于 char類型的長度.? 就是下1個地址啊. 就是指向 01100001?ascii碼就是小寫字母'a'了
?????????????
??????????? 下面就是這個例子程序


結(jié)果:



?
10.內(nèi)存如何存入int類型的負(fù)數(shù)
????
繼續(xù)用上面那個例子, 假如我定義1個int 類型的負(fù)數(shù)
?????? int i = -24930;
?????? 那么內(nèi)存里的數(shù)值是什么呢?

?????? 我們可以分析 24930的二進(jìn)制是
?????? 00000000? 00000000 0110000101100010
????

??? 本文第1張插圖已經(jīng)提過int 類型最高位是用來代表正負(fù)的. 所以加上正負(fù)位:
? ??
10000000? 00000000 0110000101100010

???
那么內(nèi)存里的數(shù)據(jù)就是上面那個二進(jìn)制數(shù)嗎?

?????? 不是的因為實際上負(fù)數(shù)是按補(bǔ)碼形式來存儲的,? 而負(fù)數(shù)的補(bǔ)碼是取反再+1
??????

10000000? 00000000 01100001 01100010??????
1
1111111??? 11111111? 1001111010011101
? ???? 先取反(符號位忽略)
11111111??? 11111111? 10011110 10011110 ? ? ? 再+1

??
上面第3行的就是-24930 在內(nèi)存中的數(shù)據(jù)了

gdb的信息

總結(jié)

以上是生活随笔為你收集整理的C语言 关于指针的格式化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。