鍍金池/ 教程/ C/ 練習(xí)21:高級(jí)數(shù)據(jù)類型和控制結(jié)構(gòu)
練習(xí)9:數(shù)組和字符串
練習(xí)6:變量類型
練習(xí)3:格式化輸出
練習(xí)4:Valgrind 介紹
練習(xí)28:Makefile 進(jìn)階
練習(xí)14:編寫并使用函數(shù)
練習(xí)21:高級(jí)數(shù)據(jù)類型和控制結(jié)構(gòu)
練習(xí)20:Zed的強(qiáng)大的調(diào)試宏
練習(xí)18:函數(shù)指針
練習(xí)0:準(zhǔn)備
練習(xí)15:指針,可怕的指針
練習(xí)27:創(chuàng)造性和防御性編程
練習(xí)22:棧、作用域和全局
練習(xí)10:字符串?dāng)?shù)組和循環(huán)
練習(xí)8:大小和數(shù)組
練習(xí)16:結(jié)構(gòu)體和指向它們的指針
練習(xí)7:更多變量和一些算術(shù)
練習(xí)23:認(rèn)識(shí)達(dá)夫設(shè)備
練習(xí)12:If,Else If,Else
練習(xí)2:用Make來代替Python
練習(xí)1:?jiǎn)⒂镁幾g器
練習(xí)11:While循環(huán)和布爾表達(dá)式
練習(xí)5:一個(gè)C程序的結(jié)構(gòu)
練習(xí)24:輸入輸出和文件
練習(xí)25:變參函數(shù)
練習(xí)13:Switch語句
練習(xí)19:一個(gè)簡(jiǎn)單的對(duì)象系統(tǒng)
練習(xí)26:編寫第一個(gè)真正的程序
導(dǎo)言:C的笛卡爾之夢(mèng)
練習(xí)17:堆和棧的內(nèi)存分配

練習(xí)21:高級(jí)數(shù)據(jù)類型和控制結(jié)構(gòu)

這個(gè)練習(xí)是C語言中所有可用的數(shù)據(jù)類型和控制結(jié)構(gòu)的摘要。它也可以作為一份參考在補(bǔ)完你的知識(shí),并且不含有任何代碼。我會(huì)通過創(chuàng)建教學(xué)卡片的方式,讓你記住一些信息,所以你會(huì)在腦子里記住所有重要的概念。

這個(gè)練習(xí)非常有用,你應(yīng)該花至少一周的時(shí)間來鞏固內(nèi)容并且補(bǔ)全這里所沒有的元素。你應(yīng)學(xué)出每個(gè)元素是什么意思,以及編寫程序來驗(yàn)證你得出的結(jié)論。

可用的數(shù)據(jù)類型

int

儲(chǔ)存普通的整數(shù),默認(rèn)為32位大小。

譯者注:int在32或64位環(huán)境下為32位,但它不應(yīng)該被看作平臺(tái)無關(guān)的。如果需要用到平臺(tái)無關(guān)的定長(zhǎng)整數(shù),請(qǐng)使用int(n)_t。

double

儲(chǔ)存稍大的浮點(diǎn)數(shù)。

float

儲(chǔ)存稍小的浮點(diǎn)數(shù)。

char

儲(chǔ)存單字節(jié)字符。

void

表示“無類型”,用于聲明不返回任何東西的函數(shù),或者所指類型不明的指針,例如void *thing。

enum

枚舉類型,類似于整數(shù),也可轉(zhuǎn)換為整數(shù),但是通過符號(hào)化的名稱訪問或設(shè)置。當(dāng)switch語句中沒有覆蓋到所有枚舉的元素時(shí),一些編譯器會(huì)發(fā)出警告。

類型修飾符

unsigned

修改類型,使它不包含任何負(fù)數(shù),同時(shí)上界變高。

signed

可以儲(chǔ)存正數(shù)和負(fù)數(shù),但是上界會(huì)變?yōu)椋ù蠹s)一半,下界變?yōu)楹蜕辖纾ù蠹s)等長(zhǎng)。

譯者注:符號(hào)修飾符只對(duì)char*** int有效。*** int默認(rèn)為signed,而char根據(jù)具體實(shí)現(xiàn),可以默認(rèn)為signed,也可以為unsigned。

long

對(duì)該類型使用較大的空間,使它能存下更大的數(shù),通常使當(dāng)前大小加倍。

short

對(duì)該類型使用較小的空間,使它儲(chǔ)存能力變小,但是占據(jù)空間也變成一半。

類型限定符

const

表示變量在初始化后不能改變。

volatile

表示會(huì)做最壞的打算,編譯器不會(huì)對(duì)它做任何優(yōu)化。通常僅在對(duì)變量做一些奇怪的事情時(shí),才會(huì)用到它。

register

強(qiáng)制讓編譯器將這個(gè)變量保存在寄存器中,并且也可以無視它。目前的編譯器更善于處理在哪里存放變量,所以應(yīng)該只在確定這樣會(huì)提升性能時(shí)使用它。

類型轉(zhuǎn)換

C使用了一種“階梯形類型提升”的機(jī)制,它會(huì)觀察運(yùn)算符兩邊的變量,并且在運(yùn)算之前將較小邊的變量轉(zhuǎn)換為較大邊。這個(gè)過程按照如下順序:

  • long double
  • double
  • float
  • long long
  • long
  • int (short, char)

譯者注:shortchar會(huì)在運(yùn)算之前轉(zhuǎn)換成int。同種類型的unsignedsigned運(yùn)算,signed保持字節(jié)不變轉(zhuǎn)換成unsigned

類型大小

stdint.h為定長(zhǎng)的整數(shù)類型定義了一些typedef,同時(shí)也有一些用于這些類型的宏。這比老的limits.h更加易于使用,因?yàn)樗遣蛔兊摹_@些類型如下:

int8_t

8位符號(hào)整數(shù)。

uint8_t

8位無符號(hào)整數(shù)。

int16_t

16位符號(hào)整數(shù)。

uint16_t

16位無符號(hào)整數(shù)。

int32_t

32位符號(hào)整數(shù)。

uint32_t

32位無符號(hào)整數(shù)。

int64_t

64位符號(hào)整數(shù)。

uint64_t

64位無符號(hào)整數(shù)。

譯者注:當(dāng)用于對(duì)類型大小有要求的特定平臺(tái)時(shí),可以使用這些類型。如果你怕麻煩,不想處理平臺(tái)相關(guān)類型的今后潛在的擴(kuò)展的話,也可以使用這些類型。

下面的模式串為(u)int(BITS)_t,其中前面的u代表unsigned,BITS是所占位數(shù)的大小。這些模式串返回了這些類型的最大(或最?。┲怠?/p>

INT(N)_MAX

N位符號(hào)整數(shù)的最大正值,例如INT16_MAX。

INT(N)_MIN

N位符號(hào)整數(shù)的最小負(fù)值。

UINT(N)_MAX

N位無符號(hào)整數(shù)的最大正值。為什么不定義其最小值,是因?yàn)樽钚≈凳?,不可能出現(xiàn)負(fù)值。

警告

要注意,不要從字面上在任何頭文件中去找INT(N)_MAX的定義。這里的N應(yīng)該為特定整數(shù),比如8、16、32、64,甚至可能是128。我在這個(gè)練習(xí)中使用了這個(gè)記法,就不需要顯式寫出每一個(gè)不同的組合了。

stdint.h中,對(duì)于size_t類型和足夠存放指針的整數(shù)也有一些宏定義,以及其它便捷類型的宏定義。編譯器至少要保證它們?yōu)槟骋淮笮?,并允許它們?yōu)楦蟮拇笮 ?/p>

int_least(N)_t

至少N位的整數(shù)。

uint_least(N)_t

至少N位的無符號(hào)整數(shù)。

INT_LEAST(N)_MAX

int_least(N)_t類型的最大值。

INT_LEAST(N)_MIN

int_least(N)_t類型的最小值。

UINT_LEAST(N)_MAX

uint_least(N)_t的最大值。

int_fast(N)_t

int_least(N)_t相似,但是是至少N位的“最快”整數(shù)。

uint_fast(N)_t

至少N位的“最快”無符號(hào)整數(shù)。

INT_FAST(N)_MAX

int_fast(N)_t的最大值。

INT_FAST(N)_MIN

int_fast(N)_t的最小值。

UINT_FAST(N)_MAX

uint_fast(N)_t的最大值。

intptr_t

足夠存放指針的符號(hào)整數(shù)。

uintptr_t

足夠存放指針的無符號(hào)整數(shù)。

INTPTR_MAX

intptr_t的最大值。

INTPTR_MIN

intptr_t的最小值。

UINTPTR_MAX

uintptr_t的最大值。

intmax_t

系統(tǒng)中可能的最大尺寸的整數(shù)類型。

uintmax_t

系統(tǒng)中可能的最大尺寸的無符號(hào)整數(shù)類型。

INTMAX_MAX

intmax_t的最大值。

INTMAX_MIN

intmax_t的最小值。

UINTMAX_MAX

uintmax_t的最大值。

PTRDIFF_MIN

ptrdiff_t的最小值。

PTRDIFF_MAX

ptrdiff_t的最大值。

SIZE_MAX

size_t的最大值。

可用的運(yùn)算符

這是一個(gè)全面的列表,關(guān)于你可以在C中使用的全部運(yùn)算符。這個(gè)列表中我會(huì)標(biāo)明一些東西:

二元

該運(yùn)算符有左右兩個(gè)操作數(shù):X + Y。

一元

該運(yùn)算符作用于操作數(shù)本身-X。

前綴

該運(yùn)算符出現(xiàn)在操作數(shù)之前:++X。

后綴

通常和前綴版本相似,但是出現(xiàn)在操作數(shù)之后,并且意義不同:X++

三元

只有一個(gè)三元運(yùn)算符,意思是“三個(gè)操作數(shù)”:X ? Y : Z。

算數(shù)運(yùn)算符

下面是基本的算數(shù)運(yùn)算符,我將函數(shù)調(diào)用()放入其中因?yàn)樗咏八銛?shù)”運(yùn)算。

()

函數(shù)調(diào)用。

二元 *

乘法。

/

除法。

二元 +

加法。

一元 +

無變化。

后綴 ++

讀取變量然后自增。

前綴 ++

自增變量然后讀取。

后綴 --

讀取變量然后自減。

前綴 --

自減變量然后讀取。

二元 -

減法。

一元 -

取反,可用于表示負(fù)數(shù)。

數(shù)據(jù)運(yùn)算

它們用于以不同方式和形式訪問數(shù)據(jù)。

->

結(jié)構(gòu)體指針的成員訪問。一元*.運(yùn)算符的復(fù)合。

.

結(jié)構(gòu)體值的成員訪問。

[]

取數(shù)組下標(biāo)。二元+和一元*運(yùn)算符的復(fù)合。

sizeof

取類型或變量大小。

一元 &

取地址。

一元 *

取值(提領(lǐng)地址)。

邏輯運(yùn)算符

它們用于測(cè)試變量的等性和不等性。

!=

不等于。

<

小于。

<=

小于等于。

==

等于(并不是賦值)。

>

大于。

>=

大于等于。

位運(yùn)算符

它們更加高級(jí),用于修改整數(shù)的原始位。

二元 &

位與。

<<

左移。

>>

右移。

^

位異或。

|

位或。

~

取補(bǔ)(翻轉(zhuǎn)所有位)。

布爾運(yùn)算符。

用于真值測(cè)試,仔細(xì)學(xué)習(xí)三元運(yùn)算符,它非常有用。

!

取非。

&&

與。

||

或。

?:

三元真值測(cè)試,X ? Y : Z讀作“若X則Y否則Z”。

賦值運(yùn)算符

復(fù)合賦值運(yùn)算符在賦值同時(shí)執(zhí)行運(yùn)算。大多數(shù)上面的運(yùn)算符都可以組成復(fù)合賦值運(yùn)算符。

=

賦值。

%=

取余賦值。

&=

位與賦值。

*=

乘法賦值。

+=

加法賦值。

-=

減法賦值。

/=

除法賦值。

<<=

左移賦值。

>>=

右移賦值。

^=

位異或賦值。

|=

位或賦值。

可用的控制結(jié)構(gòu)

下面是一些你沒有接觸過的控制結(jié)構(gòu):

do-while

do { ... } while(X);首先執(zhí)行花括號(hào)中的代碼,之后再跳出前測(cè)試X表達(dá)式。

break

放在循環(huán)中用于跳出循環(huán)。

continue

跳到循環(huán)尾。

goto

跳到你已經(jīng)放置label的位置,你已經(jīng)在dbg.h中看到它了,用于跳到error標(biāo)簽。

附加題

  • 閱讀stdint.h或它的描述,寫出所有可能出現(xiàn)的大小定義。
  • 查詢本練習(xí)的每一項(xiàng),寫出它在代碼中的作用。上網(wǎng)瀏覽資料來研究它如何正確使用。
  • 將這些信息做成教學(xué)卡片,每天看上15分鐘來記住它們。
  • 創(chuàng)建一個(gè)程序,打印出每個(gè)類型的示例,并驗(yàn)證你的研究結(jié)果是否正確。