C語言變量本質

變量的本質是什麼?是一段內存空間,它是程序一定時間內,運行過程中,對其進行讀寫的地方。

變量的名稱代表的是內存空間地址,除去變量迷人的外表:整型,字符型,長整型,指針類型,數組 剩下的就是內存空間。說到空間,就要注意無非大小,方圓幾里?起於何處,止於何方。

那些定義變量的時候叫整型的,或是字符型的是告訴我們世界這麼大,然而變量的心就這麼大,只能容下這麼點心事,多的承受不起。不要超過我的空間大小,我地界之外都是法外之地,到那裡苦海無邊,回頭是岸,家門之內保你無災無妄,是你的心安之處。

現在你明白了所謂變量,加上那些花花綠綠的類型都是都是騙人的,他就是一塊內存裡的給那個變量名為xxx的自留地,變量名稱就是讓你知道他的地址在哪,你需要他指引你到達你想要到達內存空間。

分配給你的自留地是個不毛之地,你要用之前你得清理,初始化它,讓他乾乾淨淨的,要不然他就不是你認為的樣子。記住沒有初始化變量就使用這是個禍害,千刀萬剮的行為,等到有問題的時候就是程序不死,你不能死,他死你更不能死。這是先輩們死在沙灘上血淚教訓,不是危言聳聽,昨天我寫的C語言翻車現場去看看就知道了。

好了言歸正傳,如果你的自留地夠大,你除了種花,種草甚至種樹都可以。瞭解變量空間的本質,你就發現原來C語言世界這麼大,有這麼多神來之筆。

請看下圖演示代碼

C語言變量本質

1 #include <stdio.h>

2 int main(int argc,char *argv[])

3 {

4 int i = 0;

5 char c = 1;

6 int j = 4417;

7

8 i = c;

9 c = j;

10

11 printf("sizeof(i)=%ld,i=%d,sizeof(c)=%ld,c=%d,c=%c\\n",sizeof(i),i,sizeof(c),c,c);

12 printf("Hex (65)=%0x, Dec (0x1141)=%d\\n",65,0x1141);

13 return 0 ;

14 }

程序會輸出什麼呢?說說你的答案?編譯不通過,報類型錯誤?很遺憾沒有!內存溢出報segment fault! 這個也沒有!!!

使用如下的編譯命令,一點錯誤也沒有

gcc -Wall -o test test.c

./test

結果輸出如下

C語言變量本質

這回明白了嗎,C語言才不關心你的變量叫什麼,你是什麼類型,他只認那個叫XXX變量的內存自留地,這地有多大。所以 i = c; 沒有任何問題 ,i,c 的空間大小分別為sizeof(i)=4,而sizeof(c)=1 i 容下 c 一點壓力都沒有,但c = j; 呢為什麼沒有內存溢出呢?答案是編譯器幫你自動轉換了,j的十六進制值是0X1141,被截斷了j的高位字節,只取了第一個字節41所以變成c的數值是65,ASCII碼對應的字符是A。對於C語言來說c這個變量只有種一盤花的空間,是種不下j這個大樹的,結果只能砍掉這棵樹一部分再分給c變量。

從上面可以看到C語言給了開發人員很大的自由,這種自由更接近計算機底層本質上處理過程,因為對於計算機來說這個是個空間,只是你要讀寫多少的數據問題。只要這個空間是你的進程可訪問的地址那麼是不受限制的,你需要自己維護這個空間裡數據的完整、一致性、乾淨,給自己留一片淨土。所以不要執迷於變量的類型,受困於這個類型到底能不能賦值,能不能這樣。自留地是你的,你想種什麼花,什麼草,什麼樹那是你的自由。

明白這個你就知道了你定義了一個緩衝char array[1024](什麼緩衝?沒錯這叫緩衝 ,教材叫字符數組,到你那就成了字符串)這個緩衝能放結構類型,能放長整型,能放字符型,浮點型等等。假如有這個一個需求你需要跟銀行進行代收業務交易。你交易的協議約定如下

首1,2字節是包長度 數值, 第3,4,5節是版本號 字符, 第6,7,8,9,10,11字節是本次會話ID 字符往下是包體,包體內容有字符又有數值,但是又如何寫入數據呢,記住變量本質是空間,這個空間是可放不同類型(切確說是不同大小長度)內容的空間

請看下面完整的演示代碼,就明白如何寫入不同的類型了

C語言變量本質

1 #include <stdio.h>

2 #include <string.h>

3 int main(int argc,char *argv[])

4 {

5 short pkglen=512 ; /* 包長 */

6 char version[4]={"1.0"}; /* 版本 */

7 char sessionid[6]={"123456"}; /* 會話ID */

8 char buf[1024];

9 char *pBuf = buf;

10

11 /* 封裝數據包 */

12 *((short *)pBuf) = pkglen;

13 pBuf = pBuf +2;

14 sprintf(pBuf,version);

15 pBuf = pBuf + strlen(version);

16 sprintf(pBuf,sessionid);

17 pBuf = pBuf +strlen(pBuf);

18

19 /* 解析包 */

20 pBuf = buf;

21 short len = *((short *)pBuf);

22 char v[4];

23 strncpy(v,pBuf + 2,3);

24 v[3]='\\0';

25 char s[6];

26 strncpy(s,pBuf + 2 +3,5);

27 s[5]='\\0';

28 printf("pkglen=%d,version=%s,sessionid=%s\\n",len,v,s);

29 return 0 ;

30 }

結果如下

C語言變量本質

接著來說說變量的類型,類型切確的說是在C語言中對變量進行操作時每次處理的位寬,例如int 在64位,gcc編譯器下屬

4字節的長度,對某個變量的讀寫每次都是相同的位寬,也是指針前進後退的步長。類型的作用就是告訴計算機每次處理的單元大小

看一下如下代碼演示

C語言變量本質

1 #include <stdio.h>

2 #include <string.h>

3 int main(int argc,char *argv[])

4 {

5 char array[11]="";

6 strncpy(array, "1234567890", 10);

7 char *p = array;

8

9 p++;

10 printf("*p = %c, addr = %ld\\n",*p, p);

11

12 p = p +3;

13 printf("*p = %c, addr = %ld\\n",*p, p);

14

15 int *pi =(int *) array;

16 pi++;

17 printf("*pi = %c, addr = %ld\\n",*pi,pi);

18 }

輸出:

C語言變量本質

第一次 p++; 運行後p現在的位置是相對於array 地址的下一個字節處,也就是p前進的位寬是sizeof(char),即array[1]的地址,所以打印出來的結果是2

而pi++;pi 類型的位寬是4個字節,那麼執行pi++後相當於往後走了四步sizeof(char)的大小,但只走了一步sizeof(int),可以看到程序的輸出結果最後p和pi的地址是

相等的,也就是說他們現在都是同一個地方

這就是類型的本質,它限定了每次讀寫的位寬,是按固定位寬單元去訪問。如同之前的12 *((short *)pBuf) = pkglen;

pBuf本來是char在轉換成short後寫入pkglen,直接往長度為4的內存裡寫了512,讀者想想如果是一個結構的類型呢?

總之要記住變量的本質是一段內存空間,它的名稱代表內存空間的位置,而它的類型是讀寫的位寬。


分享到:


相關文章: