前言
在介紹 C 語言的基本數(shù)據(jù)類型之前有必要先了解一下計(jì)算機(jī)內(nèi)存以及 C 語言變量相關(guān)的知識,有關(guān)計(jì)算機(jī)內(nèi)存的詳細(xì)介紹請參考深入理解計(jì)算機(jī)操作系統(tǒng)。
一、計(jì)算機(jī)內(nèi)存
計(jì)算機(jī)在執(zhí)行程序時,組成程序的指令和程序所操作的數(shù)據(jù)都必須存儲在某個地方,這個地方就是機(jī)器的內(nèi)存,也成為主內(nèi)存(main memory),或隨機(jī)訪問存儲器(RAM)。RAM 是易失性存儲器。關(guān)閉 PC 后,RAM 中的內(nèi)容就會丟失。PC 把一個或多個磁盤驅(qū)動作為其永久存儲器。
大多數(shù)計(jì)算機(jī)使用8位的塊,或者字節(jié)(byte),作為最小的可尋址的內(nèi)存單位,而不是訪問內(nèi)存中單獨(dú)的位。內(nèi)存中的每一個字節(jié)(byte)都由惟一的數(shù)字來標(biāo)識,稱為它的地址空間。
計(jì)算機(jī)內(nèi)存的常用單位是千字節(jié)(KB)、兆字節(jié)(MB)、千兆字節(jié)(GB)和兆兆字節(jié)(TB)。這些單位的意義如下:
- KB:1KB = 1024byte;
- MB:1MB = 1024KB,即 1,048,576 byte;
- GB:1GB = 1024MB,即 1,073,741,841 byte;
- TB:1TB = 1024GB,即 1,099,511,627,776 byte;
如果 PC 有 1GB 的 RAM 那么,字節(jié)地址范圍就是 0~1,073,741,841。
二、變量
變量是計(jì)算機(jī)里一塊特定的內(nèi)存,它是由一個或多個連續(xù)的字節(jié)組成,一般是1、2、4、8或16字節(jié)。每個變量都有一個名稱,可以用該名成表示內(nèi)存的這個位置,以提取它包含的數(shù)據(jù)或是存儲一個新的數(shù)值。
以下程序,會顯式你的薪水,假設(shè)你的薪水是10000刀/月(做夢都會笑醒)。
#include <stdio.h>
int main()
{
printf("My salary is $10000.\n");
return 0;
}
修改該程序,使之能夠根據(jù)內(nèi)存中的值,定制要顯示的信息。這就需要使用變量。在該示例中可以分配一塊叫做 salary 的內(nèi)存,把值10000存儲在該變量中。
#include <stdio.h>
int main()
{
int salary;
salary = 10000;
printf("My salary is $%d.\n",salary);
return 0;
}
給變量賦予的名稱稱為變量名,變量名可以是一個或多個大小寫字母、數(shù)字和下劃線(有時下劃線“_”也算作字母),但要以字母為開頭。變量名的命名規(guī)范這里不展開介紹。
2.1、變量聲明和定義
上面的示例中,存放薪水的語句如下:
int salary;
該語句稱為變量聲明,它聲明了變量的名稱,在該示例中變量名是 salary。聲明也指定了變量存儲的數(shù)據(jù)類型,這里是用 int 指定,salary 用來存放一個整數(shù)。
關(guān)于 C 語言變量的聲明和定義可以簡單概括為:
變量定義:用于為變量分配存儲空間,還可為變量指定初始值。程序中,變量有且僅有一個定義。
變量聲明:用于向程序表明變量的類型和名字。
定義也是聲明,extern 聲明不是定義
上面的變量聲明(區(qū)別使用 extern 聲明)也稱為變量的定義,因?yàn)樗峙淞艘恍┐鎯臻g,用來存放存儲整數(shù)值,該整數(shù)可以使用變量名 salary 來引用。
下面通過賦值語句為變量 salary 指定數(shù)據(jù),語句如下:
salary = 10000;
在該語句之前該變量包含一個垃圾值,即上次使用這塊內(nèi)存空間時遺留在這里的數(shù)據(jù)。以上語句是一個簡單的算數(shù)賦值語句,它將等號右邊的值存儲到等號左邊的變量中。
這里需要注意的是,變量聲明要在賦值語句之前,不然無法通過編譯,因?yàn)樽兞吭诼暶髦笆遣淮嬖诘?。最好在聲明時就對變量進(jìn)行初始化,這可以避免對初始值的懷疑,有助于追蹤錯誤,同時也避免了使用垃圾數(shù)據(jù)。
2.2、左值和右值
左值:如果一個“表達(dá)式”可以引用到某一個對象,并且這個對象是一塊內(nèi)存空間且可以被檢查和存儲,那么這個表達(dá)式就可以作為一個左值;
右值:右值指的是引用了一個存儲在某個內(nèi)存地址里的數(shù)據(jù)。
從上面的兩個定義可以看出,左值其實(shí)要引用一個對象,而一個對象在我們的程序中又肯定有一個名字或者可以通過一個名字訪問到,所以左值又可以歸納為:
左值:表示存儲在計(jì)算機(jī)內(nèi)存的對象,可尋址,相當(dāng)于地址值;
右值:代表的為真實(shí)值,可讀,即數(shù)據(jù)值。
因?yàn)樽笾凳且粋€地址值,因此可以對左值進(jìn)行賦值操作,而右值本身就是同一個數(shù)據(jù)值,就不存在對一個數(shù)據(jù)值就行賦值的操作。
這里以 ++i 和 i++ 為例來分析左值和右值:
i++ 表示取 i 的地址,把它的值裝入寄存器,然后增加內(nèi)存中 i 的值;
++i 表示取 i 地址,增加它的內(nèi)容,然后把值放在寄存器中。
看下面這個例子:
int main(int argc, char* argv[])
{
int i = 0;
printf("%d\n",i++); // 輸出為 0,返回的是寄存器的值,而不是加后的值
printf("%d\n",i); // 輸出為 1,返回的是內(nèi)存值
printf("%d\n",++i); // 輸出為 2,返回的是內(nèi)存值
// i++ = 10; // 錯誤,i++ 運(yùn)算的結(jié)果并不是 i 變量的引用,而是一個臨時變量
++i = 10;
return 0;
}
三、數(shù)據(jù)類型
C 語言包含的數(shù)據(jù)類型,如下圖所示:

3.1、基本數(shù)據(jù)類型
基本數(shù)據(jù)類型包含數(shù)值類型和字符類型,以 32 位系統(tǒng)為例,以下類型占用字節(jié)數(shù)如下。
帶符號的整數(shù)類型:
| 類型名稱 | 所占字節(jié) |
|---|---|
| signed char | 1 |
| short | 2 |
| int | 4 |
| long int | 4 |
| long long int | 8 |
| 類型名稱 | 所占字節(jié) |
|---|---|
| unsigned char | 1 |
| unsigned short | 2 |
| unsigned int | 4 |
| unsigned long int | 4 |
| unsigned long long int | 8 |
有關(guān)數(shù)據(jù)類型和存儲空間參看《深入理解計(jì)算機(jī)操作系統(tǒng)》第二章:信息的表示和處理,這里不再贅述。
3.2、sizeof 關(guān)鍵字
sizeof 運(yùn)算符可以確定給定的類型占用多少個字節(jié)。C 語言中 sizeof 是一個關(guān)鍵字。表達(dá)式 sizeof(int) 會得到 int 類型的變量所占的字節(jié)數(shù),所得到的值是一個size_t 類型的整數(shù)。size_t 在標(biāo)準(zhǔn)頭文件 <stddef.h>(和其他頭文件) 中定義,對應(yīng)于一個基本整數(shù)類型。要注意的是在不同的中 size_t 所對應(yīng)的類型可能不同,最好使用使用 size_t 類型存儲 sizeof 運(yùn)算符生成的值,在64位機(jī)器下,被定義為long unsigned int。
示例代碼:
#include <stdio.h>
#include <stdlib.h>
int main(){
char a[30];
char *b = (char*)malloc(20*sizeof(char));
printf("sizeof(a)=%d\n",sizeof(a));
printf("sizeof(b)=%d\n",sizeof(b));
printf("sizeof(a[3])=%d\n",sizeof(a[3]));
printf("sizeof(b+3)=%d\n",sizeof(b+3));
printf("sizeof(*(b+4))=%d\n",sizeof(*(b+4)));
return 0;
}
輸出結(jié)果:
sizeof(a)=30
sizeof(b)=8
sizeof(a[3])=1
sizeof(b+3)=8
sizeof(*(b+4))=1
3.3、格式化輸出
上面 sizeof 的例子,就使用了輸出占位符,C 語言的基本數(shù)據(jù)類型的輸出占位符如下表所示:
| 基本類型 | 輸出占位符 |
|---|---|
| int | %d |
| short | %d |
| long | %ld |
| float | %f |
| double | %lf |
| char | %c |
| 字符串 | %s |
| 八進(jìn)制 | %o |
| 十六進(jìn)制 | %x |