創作內容

64 GP

[達人專欄] 跟著豬腳 C 起來:各式各樣的資料型態

作者:解凍豬腳│2018-12-02 20:00:01│贊助:1,142│人氣:2840

  前篇:跟著豬腳 C 起來:用電腦來操控資料吧

  講完了電腦儲存資料的基本概念以後,我們緊接著要來認識何謂「資料型態」。

  在大部分的程式語言當中,都對這些資料的「型態」做了規範。例如我們今天想要儲存一筆正整數,那我們就會預先告訴電腦說:「我在這裡儲存的資料是正整數,千萬不要把它誤認成別的東西了喔!」如此一來,就可以避免顯示出來的資料有問題。

  舉個例:假設今天桌上有三個沒有貼上任何標籤的罐子,裡面裝的都是無色液體,一瓶是礦泉水、一瓶是酒精、一瓶則是硫酸溶液。如果你需要補充水分,結果卻拿了硫酸溶液來喝,那後果想必是非常恐怖,因為你把不能喝的東西拿來喝了。

  這樣說起來也許有點抽象,那就實際來講講 C 語言的資料型態吧。

  在 C 語言當中,常用的資料型態及儲存範圍有以下幾種:

  字元 char(1 byte):0 ~ 255

  短整數 short(2 bytes):-32768 ~ 32767
  整數 int(4 bytes):-2147483648 ~ 2147483647
  長整數 long(4 bytes):-2147483648 ~ 2147483647

  浮點數 float(4 bytes):1.2e-38 ~ 3.4e38
  雙精度浮點數 double(8 bytes):2.2e-308 ~ 1.8e308

  ※ 1.2e-38 為科學記號,用以表示 1.2 × 10^-38,其它以此類推。

  這裡要注意:只要牽涉到 long、double 這兩個詞的,可能會因為編譯器不同而導致位元組數量不同。例如有一些 C 語言的編譯器就將 long 的大小定為 8 bytes(我手上的 Dev-C++ 附帶的編譯器則是 4 bytes)。其餘也有 long long 或是 long double 之類的型態,但一樣依編譯環境不同而相異,有興趣或有需要的可以再去找找看。

  我們上次提到了,在電腦裡面都是用 1 和 0 的組合來儲存資料,但是因為一個位元太小了,所以習慣用 8 個位元一組的方式來計量。

  以 short 來說,假設今天我想要儲存 4567 這個數,那這兩個連在一起的位元組就會分別被存入「00010001 11010111」。

  設計 C 語言的工程師為了方便(畢竟計算的時候常常需要用到負數),就把大部分的基本資料型態安插了一個稱為「補數」的機制(因為這個機制有點複雜,所以想要的人就自己去 Google 吧)。他們把大約其中一半的空間挪到負數,這樣就可以避免想用到負數的時候卻沒得使用的窘境。因此,當我們在使用 int、short、long、float、double 這幾種型態的時候,都是支援負數的。

  這也間接解釋了為何在楓之谷這款線上遊戲當中,玩家的持有金錢上限為 2,147,483,647 了,基本上我們可以推測,儲存玩家楓幣數量的資料型態大概就是使用一個 int。

  然而,有些時候我們希望表現的範圍大一點點(例如我們想要儲存一個 30 多億的數字),剛好又很確定不需要用到負數,那我們就可以使用 unsigned(無號、無負號)來修飾它:

    unsigned int x, y;
    x = 3147483647;
    y = x + 48763;
    printf("%u\n", x);
    printf("%u\n", y);

  執行結果如下:



  如此一來,我們就可以成功讓 x 和 y 的儲存範圍從 -2147483648 ~ 2147483647 變成 0 ~ 4294967295,即使儲存一組範圍在 2147483648 ~ 4294967295 之內的數字也沒有問題。另外需要注意,這裡得要使用「%u」來表示「無號十進位整數」,如果誤用了表示「有號十進位整數」的「%d」的話,那顯示出來的東西就又會變成負數了。

  上次強調過,身為一個優秀的程式設計師,必須先預想好所使用的變數可能會用到多大範圍,來決定接下來所使用的資料型態。

  double 型態固然方便,但如果我們總是把所有的變數都設為 double 的話,那就會造成佔用的記憶體空間過大,浪費電腦資源。

  所以,如果我們今天想要用 C 語言寫一個用來計算「從 1970 年 1 月 1 日至今已經經過了幾天」的程式,那我們就可以使用一個 unsigned short 來計算,這樣 0 ~ 65535 的範圍,就可以供它用到西元 2149 年都還能正常運作,卻只需佔用 2 bytes(當然如果你希望它能一直使用到西元 11761200 年而改用 unsigned int 的話,我也是沒意見啦……)。

  至於 float 跟 double,儲存的機制就更複雜了。它們除了其中第一個 bit 跟其它整數型態一樣都有正負號位之外,分成了「指數」和「小數」來儲存。詳細的原理我也不贅談(寫了的話這篇的篇幅會翻好幾倍),通常使用 float 就可以扛得住很多基本的運算,若需要更精確的計算結果再考慮改用 double。

  其中最特別的是 char。這個 char 通常用來表示「字元」,但因為電腦裡所有的資料都必須用數字來儲存,所以在 C 語言當中,儲存的文字是依照「ASCII」(美國資訊交換標準程式碼)系統來表示對應的關係。只要 Google 搜尋 ASCII,就可以查到 ASCII code 表。

    char x = 87;
    printf("%c", x);

  試著執行這兩句,就會發現 print 出來的東西是一個「W」字,跟 ASCII code 表吻合。基本上,幾乎所有的編碼在 0 ~ 126 範圍表示的內容,都是以 ASCII 為主,所以無論是繁體中文用的 Big5、簡體中文用的 GB 2312、日文用的 Shift_JIS、國際通用的 Unicode ……在這些編碼當中,想要顯示一般的英文字母和阿拉伯數字都是沒有問題的。

  因此,如果今天系統想要儲存「I am handsome.」就會需要使用連續的 14 個 byte 來儲存,這 14 個變數的內容依序如下:

  73, 32, 97, 109, 32, 104, 97, 110, 100, 115, 111, 109, 101, 46

  用十六進位表示的話就會是這樣:

  49, 20, 61, 6D, 20, 68, 61, 6E, 64, 73, 6F, 6D, 65, 2E

  如果你的手邊有 hex editor 相關軟體,那你還可以把「I am handsome.」存到記事本裡面,然後再用這類程式打開來看,就可以知道電腦是如何儲存這些文字。例圖如下:



  基本的資料型態,大概就是這樣。

  所以,如果你想要儲存這麼一句話,你可以這麼做:



  屁咧!當然不可能搞得這麼複雜。要是你真的這麼做,千萬別跟人說你的 C 語言是給豬腳教的,如果你想輸出兩百個字還不寫到死。

  為了解決這樣的麻煩,C 語言還提供了更好的方法可以一次宣告(甚至控制)一堆變數。

  下次我會說明 C 語言的陣列(array)和結構(structure)。只要會了這兩個,你的程度就會再往上提升一個檔次了。感謝你的閱覽,我們下次見啦。
 
引用網址:https://home.gamer.com.tw/TrackBack.php?sn=4213730
All rights reserved. 版權所有,保留一切權利

相關創作

同標籤作品搜尋:第一次踏入墳場就上手|從入門到入墳|從入門到放棄|C語言|程式設計|C|C++|寫程式|程式|回收業者

留言共 24 篇留言

先不管這個
快忘記有這個系列ㄌ

12-02 20:01

夜貓Nightcats
好猛毆 這個系列竟然更新了

12-02 20:03

HI
優質

12-02 20:06

死螞蟻司馬燚
阿是

12-02 20:12

梓月
快速瀏覽了一下><

12-02 20:13

恐龍化身DIO
好厲害

12-02 20:15

晶礦不足
原來我有訂閱豬腳喔> <

12-02 20:21

巴哈板孫文♫ユリ
為什麼我學校都教完了你才講解啦!

12-02 20:24

過膝襪學姐ΦωΦ
這不是課本內容嗎(x 優質教學(O

12-02 20:31

撕捏套取丟‘-ωก̀
然後就是陣列和迴圈的完美結合

12-02 20:32

呆皮的同學
我決定浪費效能讓自己方便

12-02 20:41

M@B
讚讚

12-02 20:42

夜翔
嘻嘻

12-02 21:03

芊芊
雖然看不太懂但是有認真有推

12-02 21:19

雪之王女‧F‧巧可奈
完全外行只能純推>///<

12-03 08:56

阿民
你終於忙完(打完LOL)了是吧XD

12-03 10:17

新北鯨魚粥
居然更新了

12-03 11:26

Fubuki
ㄈ谷上限已經是300e-1了

12-03 11:41

天目一個
不是 全都 用 double 嗎 多方便是不是 阿不然就 int %d %.f %f !!

12-03 20:17

天目一個
char *string=""

12-03 20:20

焰狼
關於float這邊幫補充一點,當有跨越語言種類的呼叫時,要注意兩種語言的float型態是否完全相同(實數與指數各占幾bit),如果有差異時是會出問題的。
像是C語言寫出來的function讓VB來呼叫的時候,千萬不要用到float來傳遞參數資料阿......這兩個的float雖然總長度都是32 bits,但內部的實數與指數位元長度是不一樣的,彈系統哪管你這麼多,直接就把這邊的32 bits資料給到另一邊的32 bits空間.......代誌就大條了.......

12-04 21:51

安提骷髏馬過敏首席
因為文章內的內容挑起興趣所以測試了一下,如果把 signed int 用 %u 輸出的話,結果會跟 unsigned int 用 %u 輸出一樣,這是不是代表決定的關鍵是在 printf 裡面用的參數,本身宣告只是為了 readability 啊?
我的環境是 WSL (ubuntu),編譯器是 gcc。

12-05 15:46

請問我上車80隻了沒
ftp的埠號最大只能設1024~65535

12-11 16:43

Lily らい
原來如此,真是淺顯易懂(≧∇≦)b

12-16 16:17

我要留言提醒:您尚未登入,請先登入再留言

64喜歡★johnny860726 可決定是否刪除您的留言,請勿發表違反站規文字。

前一篇:首投族的小小心得... 後一篇:FFK11 流水帳,暨 ...

追蹤私訊

作品資料夾

aa18221823巴哈的碰友們
歡迎各位參觀我的小屋,之後會不定時發小說文,有興趣的可以來觀看看更多我要大聲說昨天20:17


face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】