-
1 # IT劉小虎
-
2 # 使用者56301617983
推薦《c和指標》這本書,要從記憶體的角度去理解它,沒個記憶體都有地址,說白了,指標就是一個記憶體中存放著一個地址值,這個地址值是另一記憶體地址,此記憶體中存放著資料
-
3 # SOWORD科技言
C語言指標是C語言中最基礎同時也是難點之一,很多學習過C語言的都知道指標,最基本的用法也都知道,但是深入學習C語言就知道指標是C語言的靈魂,難點就是了解指標全面用法,以及指標和指標變數的關係。
C語言指標本身難度並不大,最讓人頭痛的是它的繁瑣。C 語言最顯著的特點,就是因為它裡面有指標。
要了解指標以及指標的執行,首先我們先了解資料儲存過程的與我們如何讀取儲存過資料的內容。
我們都知道記憶體單元是位元組,在程式中定義某個變數之後,當系統對其進行編譯時就會分配到記憶體單元位元組,每個單元自己都有自己的編號,當然就會有給它一定長度的空間,也就是地址。
由於我們可以透過地址能找到變數單元,也可以說該地址“指向”該變數單元,所以在C語言中,地址就稱為“指標”,明白一點就是透過“地址”能找到對應的記憶體單元,每個變數地址都對應一個變數指標。
至於如何執行,上面也說了指標的作用就是儲存地址值,即操作記憶體。
-
4 # C語言答疑課堂
指標是C語言一個很強大的功能,同時也是很容易讓人犯錯的一個功能,用錯了指標,輕者只是報個錯,重者可能整個系統都崩潰了。下面是大家在編寫C程式時,經常遇到的一種錯誤的使用方法,也許在你的學習和工作中就是這樣用的,很危險。
C語言例項程式如下圖所示:
這段程式比較簡單,str1指向的記憶體區域存放了一個字串“123”,把“123”賦值到str2指向的記憶體區域,編譯時會給出一個告警:
local variable "str2" used without having been initialized
意思是說,“str2”這個變數沒有初始化。我們可以不理會這個告警,並且繼續執行程式,但是“str2”在定義時沒有給初值,是一個野指標,程式執行的結果可能是非常可怕的。下面我們來詳細分析下,C語言野指標的可怕之處。
一、可怕的C語言野指標我們程式中的
strcpy(str2 , str1);
printf("str2指向的字串是 %s",str2);
這兩行程式碼註釋掉,然後執行程式,看看str2輸出的值是多少。 執行結果如下:
可見str2被系統賦予一個值3435973836,3435973836是一個記憶體的地址,也就是指標str2指向這段記憶體,這段記憶體上儲存的資料可能是其他某個程式的資料,例如儲存著“hello world!”,如下圖所示,也可能什麼資料也沒有。
如果這段記憶體儲存著其他程式的重要資料,透過strcopy函式將“123”複製給了這段記憶體,也就是修改了這個重要資料,這段記憶體儲存的資料變成了“123lo world!”,如下圖所示,那麼其他程式可能就崩掉了!
二、避免C語言野指標的方法為了防止C語言野指標帶來的災難,建議指標在定義時給一個初值,比如“NULL”,意思是不指向任何記憶體地址。然後再使用malloc函式給指標分配一塊儲存空間。修改的程式如下圖所示:
在定義str2時賦予初值“NULL”,這樣str2就不會指向任何記憶體。再透過malloc函式,申請一段空的記憶體區域,也就是沒有任何程式使用的記憶體區域,讓str2指向這段空的記憶體區域,如下圖所示,
此時再把“123”賦值到這段空的記憶體區域,這樣就安全了。程式的最後,再主動釋放掉這段記憶體區域,讓str2再次不指向任何區域。 這段C語言程式碼執行結果如下圖所示:
由結果可見,系統分配的沒有任何其他程式使用的記憶體地址是“2428680”。
-
5 # 計算機軟體知識
指標是一種的變數的型別,這種變數儲存的值是一個記憶體地址。
在C語言中,每定義一個變數,編譯器都會為其分配變數型別對應大小的記憶體,記憶體的起始地址就是變數的地址,記憶體儲存的內容就是變數的值。
int i; //編譯器為變數名為i的變數分配了記憶體。
透過變數名,我們可以讀寫變數的值。
i=10;//寫入數值10到名為i的變數。
printf("%d",i);//讀取名為i的變數的值。
透過&運算子,可以讀取變數的地址。
printf("%X",&i);//讀取了名為i的變數的地址。
透過“型別 *變數名”可以定義型別對應指標型別,指標型別存放的值是另一個變數的地址。
int *p = &i;//讀取名為i的變數的地址,寫入值(值是地址)到名為p的變數。
透過*運算子,可以獲取指標型別變數值(值是地址)的值。
int j=*p; //讀取名為p的變數值(值是地址)的值,再把值寫入到名為j的變數。
指標本身也有地址,可以定義指標儲存指標的地址。
int **pp = &p;//讀取名為p的地址,再把地址作為值寫入到名為pp的變數。
像這樣值儲存的是另一個指標型別變數的地址的指標,叫做多級指標,一般常用的只到兩、三級。
指標可以儲存函式地址
int add(int a,int b){return a+b;}
int(*pf)(int,int) = add;//讀取函式add的地址,再把地址作為值寫入到名為pf的變數。
何時使用指標
使用陣列時。陣列名就是陣列首個元素的地址。
動態分配記憶體時。動態分配的型別都是以指標返回的。
回撥。回撥需要使用函式指標。
傳參。透過傳遞指標型別,可以使修改反饋到呼叫者;在傳遞大結構時,更加高效。
指標為何讓人覺得難懂?
混淆變數的地址和變數的值,變數的地址是記憶體的編號,變數的值是變數的地址對應記憶體編號儲存的內容。指標型別變數的值儲存的是另一個變數的地址。
理解不了多級指標。指標型別變數本身有地址,可以用另一個指標變數的值來儲存。無論多少級指標,去掉指標型別的一個*號,就是指標變數的值(地址)的值的型別。
指標陣列和陣列指標。無論多少層修飾,最後一個是變數的型別。指標陣列是陣列,其每個元素都是指標;陣列指標是指標,指標的值是一個數組的地址。
-
6 # 周林ZhouLin
底下的回答其實概念不是完全對的,甚至是錯的。
而且一個簡單問題寫一堆,長篇累牘,浪費讀者時間。
野指標用一句話就可以解釋: 指向已被釋放的記憶體或者已被回收的物件的指標。
比方說,在C語言裡,你有一個指標指向某記憶體塊,當用free函式釋放了該記憶體塊時,該指標就相當於指向無效記憶體塊了,如果繼續使用,就會造成程式錯誤,俗話說就是"程式跑飛了"。
下面有網友說的一個例子,指標先指向一個分配好的記憶體塊,然後將指標指向另一個新分配的記憶體塊,導致前一個記憶體塊無法再被引用到而釋放。這不是野指標問題,是記憶體洩露問題!基本概念要搞清楚,不能誤人子弟。
-
7 # 程式設計師T哥
首先需要理解所有的變數都是放在記憶體裡的,當然也有一些是暫存器變數暫時可以忽略。而指標則是指向某一個記憶體地址的一個變數。指標可以指向字元,整形,函式,結構等各種型別的資料。而指標變數本身就是需要分配記憶體。我們公司是做嵌入式的程式碼裡指標是非常普遍的,模組控制代碼,動態記憶體分配,模組互動的結構體裡面也會很多函式指標等等。總而言之指標是c語言的核心,還有不懂的可以關注我私信哦
-
8 # 小莊讀書
C語言中的野指標通常指的是,一個指標指向的記憶體已經被系統回收了,但這個指標又沒有被置空(賦值NULL),而是繼續儲存著那塊記憶體的地址,這樣的指標通常被稱為“野指標”。
因為“野指標”的內容沒有被置空,透過它仍然可以操作那塊已經被回收的記憶體,但此時那塊記憶體可能已經被系統分配它用,這樣就會產生記憶體操作衝突,導致程式的崩潰。
而產生“野指標”通常有以下兩種情況:
1. 使用malloc/calloc動態分配的記憶體,呼叫free函式釋放之後,沒有把相應的指標賦值為NULL;
2. 函式內部定義了一個臨時變數,並返回這個變數的地址賦值給函式外部的一個指標。由於函式內部的臨時變數,在函式退出後即被釋放,使用函式內部臨時變數地址賦值的指標,在函式結束後就指向了一塊已經被釋放了的記憶體。
-
9 # 程式設計老大叔
理解指標
首先,你需要掌握兩個運算子“*”和“&”;
“&”運算子:取物件在記憶體中的地址
“*”運算子:取記憶體中地址上的物件(值);
大家一定要深刻的理解上面兩個運算子,然後才能去進一步理解指標;
int a = 100 ;這一行程式碼我想大家都沒問題。那麼“&a”返回的就是物件(變數)a在記憶體中的地址,它是一個16進位制數。
然後用“*”號去a的地址去取物件:“*(&a)”,,就能取到物件a,也就就是100 ;
接下來進入重點了,指標,本身也是一個變數(物件),它本身佔用記憶體,但是它只存地址(別人的地址),它存的誰的地址我們就稱它為指向誰的指標;
int* p = &a ;int* p_2 = new int(200) ;先不管他的型別申明,只看變數本身p和p_2。前面講到指標存放的是物件的地址,那麼可以理解為指標是一個地址變數,那麼賦值的話就需要也賦一個地址給它一個地址。int* 和char*都可以表示地址型別,它們的區別就是地址所存的值得型別不同,一個是存整型,一個是存字元型;
對指標取值的話,就是用“*”號,後面接物件地址,也就是指標變數,所以*p和*p_2就分別是a和200;
指標的運用指標並不是C/C++獨有的,像C#和java等其實也是有指標的,只不過都被語言本身用其他的方式替代和封裝了一般程式設計師接觸不到,C/C++就不一樣,它是直接將指標暴露給開發者,因為大部分牽涉到指標的都與記憶體有關,而計算機記憶體很重要,萬一出什麼問題可能系統都會崩潰,下面就簡單來看一下程式在執行時指標與記憶體之間到底是個什麼樣的關係:
先看一段程式碼:
#include <stdio.h>#include <string>#include <iostream>#include <time.h>using namespace std;class people{public:people();~people();string Name ;int age ;bool sex ;char info[1024] ;void run(){}void eat(){}private:};people::people(){}people::~people(){}int main(){people* p1 = new people();cout<<p1<<endl;cout<<&p1<<endl;cout<<sizeof(p1)<<endl;cout<<sizeof(*p1)<<endl;system("pause");return 0 ;}直接執行看結果:
分析接下來來一一進行分析:
首先people* p1 = new people();這一句是類的一個例項化,系統會給people例項化一個物件*p並且給它在堆上開闢空間,注意是在堆上,開闢的空間用來儲存物件的資料。資料包括哪些?就是物件的屬性和虛擬函式指標,但是函式並不儲存在各物件中。因此run()和eat()方法是不存在物件*p指向的記憶體處的。
cout<<p1<<endl;輸出的是00279360,這是一個地址,是系統給new people()物件分配的地址。
cout<<&p1<<endl;輸出的是0012FD90,這也是地址,但這是指標變數p本身的地址。
cout<<sizeof(p1)<<endl;
cout<<sizeof(*p1)<<endl;
透過這兩個輸出就能有更清晰的認識了,p1本身只佔用4個位元組的空間,而它所指向的物件的地址所佔的空間就很大,等於類中所有資料型別所佔空間之和。
接下來在main函數里寫一點邏輯:
圖解我們來看一下程式執行時間,指標和記憶體是怎麼工作的。這裡畫一個圖給大家:
程式在執行時,資料主要是儲存在棧、堆、程式碼區、全域性區。程式碼區主要就是存程式碼中出現的一些字元常量、方法等,比如這裡程式碼中給物件的Name屬性賦的值“xiaoli”之類的都是存在此處,然後我們透過new出來的物件,都是由堆透過計算好類中各屬性所需空間然後開闢出來的。這裡p3不是透過new開闢出來的,所以他是存在棧上的並且地址是固定的,是不能更改的,而p1和p2是能更改的。
改變地址
如此,我們三個物件互相賦值後會發生什麼呢?
對比程式碼和輸出結果我們發現了什麼?賦值後p1和p2本身的地址並無改變,但是他所指向的記憶體都程式設計p3所在的記憶體了。下面用圖解給大家看一下:
改變地址的值
如果我將程式碼中的 p2 = &p3;換成*p2=p3呢?我們看下輸出結果:
造成這種情況的原因,其實這就牽涉到指標的兩種賦值問題:一種是改變指向的地址,一種是改變本身指向地址的值p2 = &p3是改變指向地址,*p2=p3是改變指向地址的值。
-
10 # 電子及工控技術
C語言是一種比較流行的語言,在眾多的程式語言中C語言長期穩居前列的位置,足見C語言在程式設計界使用的是一種非常廣泛的一種程式語言。學過C語言的朋友都知道在學習C語言時學習指標內容是一個繞不過去的坎,要想學會C語言必須要掌握指標這個知識點,從一個方面講指標既是C語言的重點也是C語言的難點,我們只有攻下這個“堡壘”才可以說真正學會了C語言。
對C語言指標中變數地址的理解
下面我結合自己學習C語言的過程透過自己用C語言編寫微控制器程式的經驗來談談我對C語言的指標理解和簡單的應用。我們利用C語言編寫程式時當遇到陣列、字串以及記憶體的動態分配等問題時,我們這時要用指標的話往往能達到簡化程式快速處理各種資料。從這方面我們可以看到指標能為程式中的各種資料的傳遞提供了很快捷的方法。
其實指標就像組合語言中的暫存器間接定址一樣,我們訪問的地址不是暫存器中的資料,而是訪問的是暫存器的地址。我們打個比方,我們把整個記憶體比作一棟大樓,記憶體中的暫存器就好像大樓中的每個房間,為了方便尋找房間我們都把房間按一定規律編號,同樣我們也把記憶體中的暫存器編好號,當我們要到大樓裡找人的時候,我們不是直接找人而是找這個人所居住的房間號,只要把房間號找到了,那麼人就自然而然地找到了。那麼同理計算機要尋找去處理某個資料不是直接去尋找這個具體的資料而是去尋找儲存這個資料的地址。找到了儲存這個資料的地址那麼這個資料也就找到了。
因此我們就把這個儲存資料的地址稱之為變數的地址,因為這個儲存器裡儲存的是一個變數,就像大樓房間裡的人一樣,房間裡的人也是經常會變的,今天這個房間住的是張三明天李四又住進去了,所以我們把儲存變數的地址就叫變數的地址。比如有個變數我們用X表示,假如它儲存在0X01這個地址單元中,我們要取出這個變數的地址用語言表示式為&X。
對C語言中指標變數的理解
我們知道了如何取變數的地址了,那麼下面就是如何把這個變數的地址給予誰的問題了,這時候我們又要引出一個“概念”。這個“概念”名詞叫指標變數。這時我們可以定義一個指標變數P,我們如果把X這個變數的地址要賦給指標變數的話,可以這樣表達:P=&X。為了明確這個變數不是一般的變數,我們要給這個指標變數加個“標籤”用*P表示。這個標籤就像“身份證”一樣,一但加上就說明這個變數不是一個一般的變量了,我們用語言表達為:*P=&X。當然既然都是變數那麼我們在使用這些變數時先要給它們定義屬性。也就是它們屬於哪一類“人員”。
C語言指標的簡單應用舉例
以上就是我對C語言中的指標這個知識點的理解,下面我們舉個“栗子”來說明指標是如何應用的,下面我們用C語言指標來編寫一個微控制器流水燈的小程式。如下圖說表示的。
程式中傳 遞的是 buf 的地址,把這個地址值直接傳遞給函式 ShiftLeft 的形參指標變數 p,也就是 p 指 向了 buf。從小程式中可以看出我們傳遞的是指 針,不僅僅我們的子函式可以使用 buf 裡邊的值,而且還可以對 buf 裡邊的值進行改變。 此外再在說一句,只要是*p 前邊帶了變數型別如 unsignedchar,就是表示定義了一個指 針變數 p,程式中的*p,是指 p 所指向的內容。
回覆列表
不同的資料型別的主要區別在於佔用的儲存空間不同。我們知道,C 程式是執行在計算機的記憶體中的,因此 C 程式的變數也是存在於記憶體中的。C 標準規定 char 型別佔用一個位元組的儲存空間,對其他整型卻沒有做規定,現在為了解釋的方便,我們假設 int 型別的資料佔用記憶體 4 個位元組。
假設我們如下定義了兩個變數:
signed char i = 3;int j = 8;那麼,i 佔用了 1 位元組的記憶體空間,j 佔用了 4 位元組的記憶體空間,請看下圖。
方框表示記憶體空間,內部表示儲存的值。我們把記憶體逐位元組編號,方框外部的數字表示方框的編號(這樣的記憶體“編號”即所謂的“記憶體地址”)。修改變數 i 的值,實際上就是修改地址為 4000 的記憶體空間裡的值。那反過來呢?如果我修改了地址為 4000 的記憶體空間裡的值,i 的值會相應改變嗎?答案是肯定的,請繼續往下看。
上圖中的記憶體地址“4000”是我為了解釋方便隨意取的。那麼,在實際應用中,變數 i 的地址如何獲取呢?C 語言提供了“&”運算子,就是獲取變數地址的。請看下面的例子:
#include <stdio.h>int main(){signed char i = 3; int j = 8; long p1 = (long)&i; printf("p1: %ld ", p1); return 0;}我們取出了 i 的地址,把它強制轉換為 long 型(關於強制型別轉換,可參考上一節),傳遞給 p1 了。編譯執行,發現變數 i 的地址被打印出來了。這說明,C 程式變數的地址也是一個整數。
按照上面的說法,修改 i 的值除了直接對 i 賦值以外,還可以透過修改 p1 地址處的記憶體空間裡的數值。那,怎樣才能“透過修改 p1 地址處的記憶體空間裡的數值”修改 i 的值呢?
上面的程式碼例項中,我們使用了 long 型變數 p1 儲存了 i 的地址。事實上,C 語言有專門的資料型別儲存地址,定義方式也很簡單,就是:“型別描述符 * ”,例如,可以定義以下變數儲存地址:
signed char *p1 = &i;int *p2 = &j;p1 和 p2 就是 C 語言中所謂的指標型別,因為 i 是 signed char 型別的,所以定義了 signed char * 型別的指標儲存 i 的地址。j 是 int 型別的,所以定義了 int * 型別的指標儲存 j 的地址。另外,C 語言提供了“&”運算子取變數地址,與之對應的,還提供了“ * ”運算子從相應地址記憶體裡取出數值。
好了,瞭解了 C 語言的指標型別和“ * ”運算子,現在來看看如何“透過修改 p1 地址處的記憶體空間裡的數值”修改 i 的值。請看如下程式碼:
signed char *p1 = &i;*p1 = 5;printf("i=%d ", i);編譯執行,發現程式輸出“i=5”,這樣我們就實現了“透過修改 p1 地址處的記憶體空間裡的數值”修改 i 的值。
在定義變數時,” * “放在變數符號前,可以定義指標變數。在定義完指標變數後,“ * ”放在變數前,就表示從地址取值的運算子了。另外,“ * ”還可以表示乘法運算子,讀者自己思考什麼情況下,“ * ”表示乘法運算子。以上的操作,實際上就是 C 語言的指標操作,可以看出它一點也不神秘,接下來幾節,我們將繼續討論 C 語言的指標,比如為什麼 int 型別的變數 j 的地址要使用 int* p2; 定義,而不能使用 signed char* p2; 定義,使用指標為何能寫出緊湊、高效的 C 程式等等。
為什麼要使用指標?
前面幾節介紹了 C 語言中指標,也討論了陣列指標和指標陣列的區別,但歸根結底,至今我們說的都是基礎資料型別定義的指標,C 語言有複合資料型別,那麼它有複合資料型別的指標嗎?答案是肯定的,事實上,在 C 語言中複合型別指標的使用相當廣泛。
先來看看結構體指標。還是從例項出發,我們定義一個結構體型別,它有兩個成員,分別是 sleep_time(睡覺時間) 和 work_time(工作時間),然後定義這種結構體型別的變數和指標:
struct week{ double sleep_time; double work_time;};struct week w;struct week *pw = &w;可以透過結構體指標 pw 訪問 week 結構體的成員:
(*pw).sleep_time = 7.0;這樣寫有點麻煩,因此 C 語言非常貼心的提供了“->”運算子,所以我們還可以這樣透過結構體指標訪問成員:
pw->sleep_time = 7.0;為什麼要使用 C 語言中的指標
好了,現在我們已經知道 C 語言中的結構體指標怎麼使用了,鋪墊完了。但是,明明使用結構體變數 w 就能很好的讀寫 week 結構體啊,為什麼要用結構體指標呢?這不是麻煩了嗎?
為什麼要使用結構體指標,其實可以延伸到“為什麼要使用指標”,本節將以結構體指標為例討論一下這個問題。是的,僅僅訪問 week 的 sleep_time 成員,只使用結構體變數 w 就足夠了,再透過 pw 訪問真的麻煩了。但是工具會不會帶來方便,要看我們怎麼使用,不能因為高射炮打蚊子不方便就說高射炮沒用。恰當的使用結構體指標,有利於我們寫出更加緊湊,效率更高的 C 程式。
一週有五天工作日,兩天週末,一般來說,在工作日(weekday),人們的睡覺時間較短,工作時間較長,所以我們定義 weekday 函式來規劃工作日的時間:
void weekday(struct week wd){ wd.sleep_time = 7.0; // 7 小時 wd.work_time = 8.5; // 8.5 小時}而在週末(weekend)則反過來,工作間較短,睡覺時間較長,所以我們定義 weekend 函式來規劃週末的時間:
void weekend(struct week we){ we.sleep_time = 9.0; // 9 小時 we.work_time = 2.5; // 2.5 小時}這兩個函式很好的規劃了一週的睡覺和工作時間,但是卻並不好用。為什麼呢?因為它倆只在自己內部規劃了,我們外界看不到啊!想在 main 函式把規劃好的時間打印出來都辦不到,因為它倆在自己內部規劃好以後,就把“規劃書”銷燬了。
這裡把 weekday 和 weekend 函式的區域性變數比作“規劃書”,函式退出後,區域性變數就自動銷燬了。可以參考《c語言入門5,一文徹底弄懂函式的形參和實參》一節。可能你會說,那我可以把“規劃書”返回給 main 函式啊,讓 weekday 和 weekend 函式有返回值就可以了:
struct week weekday(struct week wd){ wd.sleep_time = 7.0; // 7 小時 wd.work_time = 8.5; // 8.5 小時 return wd;}struct week weekend(struct week we){ we.sleep_time = 9.0; // 9 小時 we.work_time = 2.5; // 2.5 小時 return we;}int main(){ struct week w; w = weekday(w); printf("weekday, sleep time: %0.1f, work time: %0.1f ", w.sleep_time, w.work_time); weekend(w); printf("weekend, sleep time: %0.1f, work time: %0.1f ", w.sleep_time, w.work_time); return 0;}是的,這的確是一個解決問題的辦法,main 可以把 weekday 和 weekend 函式的“規劃書”打印出來了。
但是這種解決問題的辦法有一點臃腫,很多程式設計師把這樣的程式碼稱為“不優雅”的程式碼。你看,main 現在有一份空的“規劃書”,需要 weekday 和 weekend 函式處理。weekday 和 weekend 函式能處理,但是它們要複製一份“規劃書”回到自己內部做,這種複製就造成了空間浪費。此外,weekday 和 weekend 函式做完了規劃書,還要把“規劃書”再從自己內部取出,return 給 main,這就有時間浪費。
更節約資源,更有效率的做法是:weekday 和 weekend 函式處理這份“規劃書”時,直接處理 main 裡的“規劃書”就可以了。不要複製後再處理,完事了還要在從自己內部傳出。那,weekday 和 weekend 函式應該怎麼修改呢?請看:
void weekday(struct week *wd){ wd->sleep_time = 7.0; // 7 小時 wd->work_time = 8.5; // 8.5 小時}void weekend(struct week *we){ we->sleep_time = 9.0; // 9 小時 we->work_time = 2.5; // 2.5 小時}int main(){ struct week w; weekday(&w); printf("weekday, sleep time: %0.1f, work time: %0.1f ", w.sleep_time, w.work_time); weekend(&w); printf("weekend, sleep time: %0.1f, work time: %0.1f ", w.sleep_time, w.work_time); return 0;}看到了沒,利用指標,整個 C 程式碼簡潔多了。weekday 和 weekend 函式接收到的引數都是 main 裡結構體變數 w 的地址,所以它倆都是直接操作 w 的。這樣就不用在自己的棧幀裡複製一份 w 再處理了,也不用在處理完畢還要 return 給 main 了。
看到這裡,你可能會說,什麼嘛,不就是用指標代替了結構體做引數嗎?指標說不定比結構體還要耗空間呢!對嗎?一起來看下:結構體變數 w,它佔用記憶體至少兩個 sizeof(double) 的空間(一個 double 型資料通常佔用 8 位元組空間)。而一個指標,不管它是什麼型別的,在大多數 32 位計算機中,它只佔 4 位元組空間,在大多數 64 位計算機中,它也僅僅佔 8 位元組空間。所以使用指標做 weekday 和 weekend 函式的引數,在空間上,絕對是比直接使用 week 結構體節約空間的,何況指標還提升了效率,簡潔了程式碼。
如果是一個 char 型變數,它只佔用 1 位元組空間,這時使用指標的確更浪費空間。但是如果是一個非常複雜的結構體,它佔用的記憶體空間甚至達幾千位元組,這時使用指標就非常節約空間了。所以說,工具是死的,人是活的。到這裡,相信你已經瞭解 C 語言指標在節約空間,提升程式效率方面的作用了。事實上,這裡我們介紹的僅僅是指標的冰山一角,在以後的文章裡,你會愈發覺得 C 語言指標的強大的。