周立功教授數(shù)年之心血之作《程序設(shè)計(jì)與數(shù)據(jù)結(jié)構(gòu)》,書本內(nèi)容公開后,在電子行業(yè)掀起一片學(xué)習(xí)熱潮。經(jīng)周立功教授授權(quán),本公眾號特對本書內(nèi)容進(jìn)行連載,愿共勉之。
第一章為程序設(shè)計(jì)基礎(chǔ),本文為1.8.3 指針數(shù)組。
>>>>1.字符串與指針數(shù)組
如果有以下定義:
int data0 = 1, data1 = 2, data2 = 3;
int *ptr0 = &data0, *ptr1 = &data1, *ptr2 = &data2;
實(shí)際上地址也是數(shù)據(jù),那么數(shù)組也可以保存指針,因此可以在基本數(shù)據(jù)類型的基礎(chǔ)上派生一個(gè)構(gòu)造類型,即將相同類型的指針變量集合在一起有序地排列構(gòu)成指針數(shù)組。在指針數(shù)組變量的每一個(gè)元素中存放一個(gè)地址,并用下標(biāo)區(qū)分它們。雖然數(shù)組與指針數(shù)組存儲的都是數(shù)據(jù),但還是有細(xì)微的差別。數(shù)組存儲的是相同類型的字符或數(shù)值,而指針數(shù)組存儲的是相同類型的指針。比如:
int data0, data1, data2;
int *ptr[3] = {&data0, &data1, &data2};
該聲明被解釋為ptr是指向int的指針的數(shù)組(元素個(gè)數(shù)3),“int *[3]”類型名被解釋為指向int的指針的數(shù)組(元素個(gè)數(shù)3)類型。即ptr指針數(shù)組是數(shù)組元素為3個(gè)指針的數(shù)組,其本質(zhì)是數(shù)組,類型為int *[3],ptr[0]指向&data0,ptr[1]指向&data1,ptr[2]指向&data2。
由于ptr聲明為指針數(shù)組,因此ptr[0]返回的是一個(gè)地址。當(dāng)用*ptr[i]解引用指針(i=0~2)時(shí),則得到這個(gè)地址的內(nèi)容,即*ptr[0]==1,*ptr[1]==2,*ptr[2]==3。當(dāng)然,也可以使用等價(jià)的指針表示法,ptr+i表示數(shù)組第i個(gè)元素的地址。如果要修改這個(gè)地址中的內(nèi)容,可以使用*(ptr+i)。如果對**(ptr+i)解引用兩次,則返回所分配的內(nèi)存的位置,即可對其賦值。比如,ptr[1]位于地址&ptr[1],表達(dá)式ptr+1返回&ptr[1],用*(ptr+1)則得到指針&data1,再用**(ptr+i)解引用得到&data1的內(nèi)容“1”。由此可見,使用指針的指針表示法,讓我們知道正在處理的是指針數(shù)組。
顯然,只要初始化一個(gè)指針數(shù)組變量保存各個(gè)字符串的首地址,即可引用多個(gè)字符串:
char * keyWord[5] = {"eagle", "cat", "and", "dog", "ball"};
其中,keyWord[0]的類型是char*,&keyWord[0]的類型是char **。雖然這些字符串看起來好像存儲在keyWord指針數(shù)組變量中,但指針數(shù)組變量中實(shí)際上只存儲了指針,每一個(gè)指針都指向其對應(yīng)字符串的第一個(gè)字符。也就是說,第i個(gè)字符串的所有字符存儲在存儲器中的某個(gè)位置,指向它的指針存儲在keyWord [i]中,即keyWord [0]指向“"eagle"”、keyWord [1]指向“"cat"”,keyWord[2]指向 "ant",keyWord[3]指向 "dog",keyWord[4]指向 "ball"。
盡管keyWord的大小是固定的,但它訪問的字符串可以是任意長度,這種靈活性是C語言強(qiáng)大的數(shù)據(jù)構(gòu)造能力的一個(gè)有力的證明。由于指針數(shù)組是元素為指針變量的數(shù)組,因此一個(gè)字符指針數(shù)組可以用于處理多個(gè)字符串。顯然,將字符串制成一個(gè)表存放于指針數(shù)組的話,比使用switch語句效果更好。由此可見,數(shù)據(jù)的隨機(jī)存儲會以兩種形式保存:存址和存值,存址方式詳見圖 1.14。一個(gè)數(shù)組包含了指向?qū)嶋H信息的指針,而不是直接將信息存儲在數(shù)組元素的存儲空間里。使用這種方式,可以靈活地存儲和排序任何復(fù)雜結(jié)構(gòu)的數(shù)據(jù)。
圖 1.14 存址方式
相反地,基于值的存儲將n個(gè)元素的數(shù)據(jù)集合打包存儲在固定大小的記錄塊中,這個(gè)固定大小為s,存值方式詳見圖 1.15,每個(gè)字符串占用大小為6字節(jié)的連續(xù)存儲塊。
圖 1.15 存值方式
為了便于說明多個(gè)字符串的引用,將設(shè)計(jì)一個(gè)數(shù)據(jù)交換函數(shù)。由于任何數(shù)據(jù)類型的指針都可以給void*指針賦值,因此可以利用這一特性,將void*指針作為byte_swap()函數(shù)的形參,即可接受任何類型數(shù)據(jù)。
由于C中最小長度的變量為char類型(包括unsigned char、signed char等),其sizeof(char)的結(jié)果為1,而其它任何變量的長度都是它的整數(shù)倍。比如,在32位系統(tǒng)中,sizeof(int)為4。由于C語言的變量類型多種多樣,因此不可能為每一種變量類型編號,而且swap也并不關(guān)心變量的真正類型,所以可以用變量的長度代替變量類型。byte_swap函數(shù)原型為:
void byte_swap(void *pData1, void *pData2, size_t stSize);
其中,size_t是C語言標(biāo)準(zhǔn)庫中預(yù)定義的類型,專門用于保存變量的大小。stSize為變量的長度,pData1、pData2分別為是要比較的第1、2個(gè)參數(shù)。當(dāng)返回值< 0時(shí),表示pData1 < pData2;當(dāng)返回值= 0時(shí),表示pData1 = pData2;當(dāng)返回值> 0時(shí),表示pData1 > pDta2。
在這里,任何類型的指針都可以傳入byte_swap()中,真實(shí)地體現(xiàn)了內(nèi)存操作函數(shù)的意義,無論這塊內(nèi)存是什么數(shù)據(jù)類型,它操作的對象僅僅是一塊內(nèi)存。無論用戶傳進(jìn)來的是什么類型,從C99版本后,將void *類型指針賦值給其它類型指針時(shí),不再需要強(qiáng)制類型轉(zhuǎn)換。即循環(huán)一次交換一個(gè)字節(jié),那么對于int類型數(shù)據(jù)來說,僅需循環(huán)4次就可以了。其前提是兩個(gè)變量的類型必須相同,比如,交換a、b兩個(gè)變量的值,其使用方法如下:
byte_swap(&a, &b, sizeof(a));
byte_swap()數(shù)據(jù)交換函數(shù)的接口與實(shí)現(xiàn)詳見程序清單 1.42和程序清單 1.43。
程序清單1.42swap數(shù)據(jù)交換函數(shù)接口(swap.h)
1 #pragma once
2 void byte_swap(void *pData1, void *pData2, size_t stSize);
程序清單1.43swap數(shù)據(jù)交換函數(shù)接口的實(shí)現(xiàn)(swap.c)
1 void byte_swap(void *pData1, void *pData2, size_t stSize)
2 {
3 unsigned char *pcData1 = pData1;
4 unsigned char *pcData2 = pData2;
5 unsigned char ucTemp;
6
7 while (stSize--){
8 ucTemp = *pcData1; *pcData1 = *pcData2; *pcData2 = ucTemp;
9 pcData1++; pcData2++;
10 }
11 }
針對特定的字符串,指針數(shù)組的應(yīng)用示例詳見程序清單 1.44。
程序清單1.44比較字符串大小然后輸出范例程序
1 #include
2 #include
3 #include "swap.h"
4
5 const char * keyWord[5] = {"eagle", "cat", "and", "dog", "ball"};
6 void show_str (void) //打印keyWord數(shù)據(jù)
7 {
8 for (int i = 0; i < sizeof(keyWord) / sizeof(keyWord[0]); i ++){
9 printf("%s", keyWord[i]);
10 }
11 printf("\n");
12 }
13
14 int main(int argc, char *argv[])
15 {
16 show_str();
17
18 if(strcmp(keyWord[0], keyWord[1]) < 0)
19 byte_swap(keyWord, keyWord +1, sizeof(keyWord[0]));
20 show_str();
21 return 0;
22 }
-
指針
+關(guān)注
關(guān)注
1文章
481瀏覽量
70611
原文標(biāo)題:周立功:你知道數(shù)組也能保存指針嗎?
文章出處:【微信號:ZLG_zhiyuan,微信公眾號:ZLG致遠(yuǎn)電子】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
經(jīng)典著作《C和指針》
基礎(chǔ)知識講解:LED色溫和顯色指數(shù)的介紹
C語言基礎(chǔ)教程之指針的知識點(diǎn)和使用總結(jié)
![C語言基礎(chǔ)教程之<b class='flag-5'>指針</b>的<b class='flag-5'>知識</b>點(diǎn)和使用總結(jié)](https://file.elecfans.com/web1/M00/6C/F3/pIYBAFvqrwqANb1eAACtSLf3Z3I965.png)
C和指針課后題答案完整版免費(fèi)下載
C和指針的電子書免費(fèi)下載
043-ACMICPC相關(guān)知識
![043-ACMICPC<b class='flag-5'>相關(guān)</b><b class='flag-5'>知識</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
總降調(diào)度相關(guān)知識
![總降調(diào)度<b class='flag-5'>相關(guān)</b><b class='flag-5'>知識</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
指針才是C語言的精髓
![<b class='flag-5'>指針</b>才是C語言的精髓](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
數(shù)組相關(guān)的雙指針算法
C語言_字符串與指針的練習(xí)
C語言中指針及其相關(guān)知識
晶體知識——晶向指數(shù)和晶面指數(shù)
![晶體<b class='flag-5'>知識</b>——晶向<b class='flag-5'>指數(shù)</b>和晶面<b class='flag-5'>指數(shù)</b>](https://file1.elecfans.com/web2/M00/AD/EE/wKgaomVRxBSAPeCXAABA_0yexvU298.png)
評論