C語言之二進制的資料記錄觀念
本節我們介紹C語言如何定義資料格式做為仲介人與電腦能夠共享資料的標準。依據需要處理的數據特性,C語言提供了多種資料格式(Data Type)可供選擇。包括字元型態Character,整數型態Integer,以及浮點數型態Floating Point 等三類。每一類又可以細分。
在正式介紹各種格式的資料型態前,我們先介紹二進制的資料記錄觀念,2進制的資料是由許多個能存放0與1兩種狀態的記憶單元共同組成,每一單元稱為一個位元1Bit,在C語言中處理或存取資料一次最少就是8個位元8Bits,因此每8個位元另有一個單位叫做位元組Byte。依據資料長度,由短到長:
1. 字元Char:主要用來存放包括;英文字母,阿拉伯數字,各式運算符號以及鍵盤,印表機與操制台等設備控制碼。這些碼叫做字元,是按照美國通訊協會訂定的標準來決定,稱之為ASCII碼。ASCII碼數目只要1BYTE就足夠存放。因此字元型態的資料基本上只佔1BYTE。由於1BYTE可以有效編出256個位置,它除了可以存放字元,也可以存放-128到127帶正負號的整數 char。若是數值在0到255之間正整數則用unsigned char來存。至於是字元或則整數,則由程式設計者自己來決定,並且依據自己的決定來使用。倘若自己規定是字元郤當成整數來用,錯用了也要由自己負責。
2. 整數Int :主要用來存放整數,依據欲存資料的可能大小範圍,以AVR微控器來說 ,可以用2BYTE 大小的型態 int,來存放-32768 ~ 32767範圍的整數,或則是用4BYTE 大小的型態 long int 來存-2147483648 ~ 2147483647 範圍的整數。若是要存的值永遠是正數,則如同char一樣,可以在前面加上一個unsigned,如unsigned short int, unsigned long int。 如同char名為字元但實際上可以存放字元也可能存放整數,int雖然名為整數,但其實也可能存放含整數部份及小數部份的數值。以10進位數值為例,2013與20.13的差別就在小數點點在最後與往前移兩個位置。2進位的1010代表的是10,而2 1/2則代表或則是10/4。2進位的數,小數點每往左移一位,則數值除一個2。至於說小數點在那裏,資料裏並沒有明確標示,完全由程式設計師自己自由決定,並由自己來估算計算過後的小數點位置。這種方式的數值小數點位置固定在程式之內,是為固定小數點數值fixed point ,簡稱定點數。
3. 浮點數float: 專門用來存放含整數部份及小數部份的數值。浮點數型態需用4BYTES共32BITS的空間來存放資料,其中只保留24BITS來存放數值,其餘8BITS則用於存放指數,亦即小數點位移的資訊。相對於定點數,浮點數的小數點由於可以依據存入數值的大小動態調整並記錄在指數部份,因此用樣的BITS數下,它可以記錄數值的精度及動態範圍可以擴大到 3.4E-38~3.4E38。雙精度double 則需用8BYTES共64BITS來記錄數值,其中數值部份佔用55BITS,留11BITS來記錄指數部份。其精度及範圍則可達到 1.7E-308~1.7E308。
4. 無型void: 非特定型態。由於C編譯時會檢查型態是否吻合,不吻合時會提出警告或表示錯誤,指定變數為無型可以免除這些檢查,以方便程式設計者可以執行低階的命令直接控制電腦硬體,這在一般的C程式語言應用很少用到,但對微控器的控制,以及作業系統層級的程式來說郤是很好用的後門
變數Varialbe
顧名思義,變數是指內容值會變動的數,在數學方程式是要被解出來或被指定進去的值,在電腦中,則需要有一個記憶體空間可以存放這個會被指定或被解出來的值。因此在C語言的變數,需要有變數名稱以備標示存放變數內容的記憶體位置location value ,需要有變數型態以備指變數所需容間的大小,以及對這個變數進行處理時所需依循的規則,準備好了空間以及規則後可用這個記憶體空間存取數值內容read value rvalue。
在C語言裏要使用一個變數,必需先為這個變數取一個名稱,規定其合法的運算方式及大小,這個動作在C語言的術語稱為宣告Declaration ,並且依據宣告格式找一個記相應大小的憶體空間定義Definition 出這一個變數,在寫法上兩者都一樣,
例如
int nameOfStuden;
其中int為指出變數型態,除了介定了這個變數的記憶體大小,同時也限定了這個變數未來的合法操作方式。 NameOfStuden則給了變數的名稱在函式之內的後面的程式行中只要提到這個字串,就是指這一個變數。至於是宣告Declaration 或是定義Definition ,只有在處理擁有多筆資料的變數,如字串,矩陣及資料結構等時,比較有明顯不同,因此相關細節待後續再討論。
單筆資料的變數,一般書本都只講宣告, C語言的處理這行程式時,會為這個名為 nameOfStuden的變數創造一個記憶體空間,並連接這個記憶體空間的位址到這個名稱上。
早期許多C教材會鼔勵利用匈牙利命名法,在變數名稱前加上它的特性,例如intNum, 但現在教學已不再特別推廣,現在多以能夠說明這個變數的字串相連,並且除了第一個字的第一個字母為小寫外,其它字的第一個字母為大寫。例如nameOfStudent, sizeOfWord,第一個字大寫的名稱保留給系統使用。或則在字與字之間加入”_”,如name_of_student, size_of_word 。
這裏我們必需強調,在宣告/定義之後,變數空間是找到了,名子與位址也牽上了線,但變數的內容因為仍然非我們所指定的,因此仍然為未知值,需要初始化initialization,才能夠有內容。
常數及初始化Literal Constant & Initialization
前面在說明printf()的範例之中,如:
程式中如果有純阿拉伯數字的組合,則編譯器會將它視為常數,稱為文字常數literal constant。前面在說明printf()的範例之中,如:
printf("Decimate number %d in hexidecimate is %x\n", 15,15);
函式中的兩個15,即為均為文字常數。文字常數除了能夠直接拿來輸出以及做運算如
A=B+15;
它也是將數值填進變數,幫變數初始化的必要數值來源。例如
int NumberOfStudents=30;
除了為變數 NumberOfStudents以int 宣告為整數型態之外,為他取得定義出記憶體位址並也將數值內容初始化為30。
文字常數,不論是輸出顯示,參與運算,或則是初始化變數,均會與變數交換資料訊息,互動的變數之間有其資料型態要吻合,與其互動的文字常數也同樣要滿足資料型態吻合的限制。為提供程式設計者一個彈性空間,可以書寫10進制,2進制,以及16進制等各式的文字常數。
10進制常數,每個位數最大為9超過9即進位到下一數位。每一位數用均可用阿拉伯數字0~9來代表,多個位數串即為,成為一個10進位數值,由於10進位是最常用的常數表示法,所以在C語言中,以10進位表達的常數,不必增加任何標示。
2進制常數,每個位數最大為1超過1即進位到下一數位。 每一位數可用阿拉伯數字0或1來代表,多個0或1的位數串即可表示2數值,但為了與10進位數值區隔,在0或1字串的前加上『0b』以表示後面所接續的是2進字數值。
16進制常數,每個位數最大為15超過15即進位到下一數位。 阿拉伯數字只有0到9不夠用,因此16進制碼加入了A~F來代表高於9的數值。也就是說,A代表10,B代表11,依序直到F代表15,多個0~9,A~F的位數串即可表示16進位數值,但為了與其它2進或10進位數值區隔,16進制則要在數位字串之前加上『0x』。
有三個變數A,B,C都被初始成85,我們可以分別使用三種不同進制的文字常數來初始它們,結果都是一樣的。
C語言中,16進制會以0x做為16進制碼字串的開頭後面接2個16進制碼,可以表示一位元組共八位元的值。
例如
0b0000 1111 = 15 = 0x0F 。
0B1010 1100=10*16+12=172=0xAC。
例如
#include “C4MLib.h”
int main(void) {
C4M_DEVICE_set();
int a,b;
a=85; // 8x10^1+5=80+5=85
b=0x55; // 5x16^1+5x16^0=80+5=85
c=0b01010101; // 1x2^6+1x2^4+1x2^2+1x2^0= 64+16+4+1=85
printf(“A=%d\n,B=%d\n,C=%d\n”,a,b,c);
}
結果程式輸出
A=85
B=85
C=85
日常生活中,最常見的常數就是10進制整數,及實數,2進制及16進制只有電子工程師,電腦硬體工程師,機電工程師這些人會比較常用到,10進制16進制所有C編輯器應該都支援
C編譯器在選到純整數,以及小數時,能夠自動辨識並給予對的資料型態。
例如
範例:
#include "C4MLib.h"
int main(void)
{
C4M_DEVICE_set();
while(1)
{
printf("sizeof(1):\t %d bytes\n",(int)sizeof(1));
printf("sizeof(1.0):\t %d bytes\n",sizeof(1.0));
}
return 0;
}
執行結果
若1被認定為整數int,假設在AVR 微控器C中1是short int則佔用2 Byte。設0.1被認定是浮點數float則佔用4Bytes 。其中 sizeof()函式是C函式庫提供的函式,可以算出其輸入值的位元組(bytes)數。
Sizeof(1): 2bytes
sizeof(1.0): 4bytes
設若1及0.1被認定是long 及 double,則
Sizeof(1): 4bytes
sizeof(1.0): 8bytes
自己用電腦試試看,便可以了解自己用的編譯器是如何對待整數及實數。
若需要字元型態的文字常數,可以用『'』放在字母的前後,如
char character='A';
有些字元是被C保留為保留字元,具有它在C語言中的定義,這些字元要用文字常數方式初始化變數時,必需在其左邊加上逃脫符號『\』以通知C編譯器。除了保留字元外,一些控制鍵盤的功能鍵如backspace等都是不可見字元,都需要逃脫符號『\』如下表