計(jì)算機(jī)的計(jì)算和存儲(chǔ)都是數(shù)據(jù)弯洗。在C語(yǔ)言里耳标,數(shù)據(jù)同樣是基礎(chǔ)雏节,學(xué)好數(shù)據(jù)的知識(shí)是必須的胜嗓。
先看一個(gè)最簡(jiǎn)單的例子
#include <stdio.h>
int main(void)
{
int weight;
float cost;
float value;
printf("please input your weight.\n");
scanf("%d", &weight);
printf("please input your single cost.\n");
scanf("%f", &cost);
value = weight * cost;
printf("your total cost is %.2f\n", value);
return 1;
}
C中的基本數(shù)據(jù)類型如下,而我們可以把他們分成兩類(整數(shù)類型钩乍、浮點(diǎn)數(shù)類型)辞州。
K&R關(guān)鍵字:int、long寥粹、short变过、unsigned埃元、char、float媚狰、double
C90新增:signed岛杀、void
C99新增:_Bool、_Complex崭孤、_Imaginary
整數(shù)类嗤,就是不帶小數(shù)點(diǎn)的數(shù)。浮點(diǎn)數(shù)辨宠,整數(shù)之間的那些數(shù)遗锣。
一、int類型
C之所以提供多種整數(shù)類型彭羹,原因在于為程序員針對(duì)不同用途場(chǎng)景提供多種選擇黄伊。C的整數(shù)類型間的區(qū)別在于其提供數(shù)值的范圍和是否可以取負(fù)。int是基本類型派殷,我們可以根據(jù)任務(wù)和機(jī)器選擇其他類型。
1墓阀、聲明int類型毡惜。為變量賦值,可以在聲明的時(shí)候賦值斯撮,還可以通過(guò)scanf的方式经伙。
int param;
int cows, dogs;
int weight, cost = 3; // 盡量避免這樣的聲明,因?yàn)閺淖置嫔细杏X(jué)weight也是被賦值為3了勿锅。實(shí)際上帕膜,weight仍然是未賦值狀態(tài)。
scanf("%d", &cows);
2溢十、十進(jìn)制垮刹、八進(jìn)制、二進(jìn)制和十六進(jìn)制
計(jì)算機(jī)內(nèi)部數(shù)據(jù)表示使用的是二進(jìn)制张弛,它帶來(lái)的好處是簡(jiǎn)單荒典,它只有兩個(gè)數(shù)值0和1。
十進(jìn)制是我們?nèi)粘5谋硎痉椒ㄍ萄迹覀內(nèi)擞惺畟€(gè)手指頭寺董,數(shù)值為0-9。
雖然二進(jìn)制很簡(jiǎn)單刻剥,但是書(shū)寫(xiě)起來(lái)卻是很麻煩的一件事遮咖,所以我們可以把3個(gè)二進(jìn)制位表示為八進(jìn)制;把4個(gè)二進(jìn)制位表示為十六進(jìn)制造虏。同二進(jìn)制和十進(jìn)制一樣御吞,八進(jìn)制數(shù)值為0-7麦箍,十六進(jìn)制數(shù)值為0-9、A-F魄藕。
聲明進(jìn)制如下:
十進(jìn)制 | 八進(jìn)制 | 十六進(jìn)制 |
---|---|---|
int a = 13 | int a = 015 | int a = 0xD |
打印如下:
十進(jìn)制 | 八進(jìn)制 | 十六進(jìn)制 |
---|---|---|
%d | %o | %x |
%d | %#o | %#x |
3内列、其他整數(shù)類型(short、long背率、unsigned话瞧、signed修飾)
[a->signed|unsigned] | [b->short|long|long long] | [c->int] param
當(dāng)a或者b存在時(shí),可以省略c寝姿;如果類型本身為有符號(hào)數(shù)交排,可省略signed。
例如:
int a;
long int estate;
long johns;
short int eyes;
short count;
unsigned long etc;
signed int gg;
signed cool;
long long ago;
在聲明long和無(wú)符號(hào)常量時(shí)饵筑,我們可以使用后綴u代表無(wú)符號(hào)埃篓,使用l或L代表長(zhǎng)整形。比如:3uLL根资、3ULL架专、3ull、3ul玄帕、3Ull部脚。但是我們一般使用L,而非l裤纹,因?yàn)閘和大寫(xiě)的i很像委刘。
要打印這些類型時(shí),我們可以考慮一些規(guī)則鹰椒。signed使用%d锡移,unsigned使用%u,long使用%l(小寫(xiě)的L)漆际,short使用%h淆珊,他們可以和進(jìn)制結(jié)合起來(lái)(再?gòu)?fù)習(xí)一下,o表示八進(jìn)制灿椅,x表示十六進(jìn)制套蒂,#表示顯示進(jìn)制符號(hào)——0/0x)。
例如:
#include <stdio.h>
int main(void)
{
unsigned int un = 30000000;
short end = 200;
long big = 65537;
long long verybig = 12345678908642;
printf("un = %u and not %d\n", un, un);
printf("big = %ld and not %hd\n", big, big);
printf("verybig = %lld and not %ld\n", verybig, verybig);
return 1;
}
二茫蛹、char類型
char類型使用一個(gè)字節(jié)來(lái)表示操刀,一個(gè)字節(jié)有8個(gè)二進(jìn)制位,所以最多有256個(gè)可能數(shù)婴洼,標(biāo)準(zhǔn)ASCII編碼范圍從0~127骨坑。而一些系統(tǒng)對(duì)其進(jìn)行了擴(kuò)展,但也是限定在8位之內(nèi)。
1欢唾、聲明
char response;
char iter, latan;
2且警、常量及初始化
char類型理論上仍然是一個(gè)數(shù)字,所以我們可以使用范圍內(nèi)的int來(lái)表示礁遣。另外斑芜,我們也可以使用字符用單引號(hào)引起來(lái)表示。例如:
char boild = 'A';
char let = 65;
char etc = '\n';
3祟霍、轉(zhuǎn)義字符
正如\n所表示杏头,有時(shí)我們需要轉(zhuǎn)義字符,比如:回車沸呐、換行醇王、跳格、制表符等崭添。轉(zhuǎn)義字符的聲明是使用反斜杠+特殊說(shuō)明來(lái)表示寓娩。這兒的特殊說(shuō)明可以簡(jiǎn)單列舉如下:
字符 | 意義 |
---|---|
\n | 換行 |
\b | 退格 |
\0oo | 八進(jìn)制值(o表示一個(gè)八進(jìn)制數(shù)字) |
\xhh | 十六進(jìn)制值(hh表示一個(gè)十六進(jìn)制數(shù)字) |
上述表格中,我們尤其強(qiáng)調(diào)一下八進(jìn)制值和十六進(jìn)制值呼渣。我們?yōu)槭裁匆@樣表示棘伴,而不直接使用0oo和0xhh表示呢。有兩個(gè)原因屁置,一個(gè)是前者能很直觀地表述程序員的意圖(是一個(gè)字符排嫌,而非數(shù)字),另一個(gè)原因是前者可以方便地嵌入到字符串中缰犁,例如:"\007"。
三怖糊、_Bool
這個(gè)類型是c99才引入的帅容,它只有兩個(gè)值:0和1,1代表true伍伤,0代表false并徘。
四、inttype.h扰魂,引入可移植類型
上述整數(shù)類型已經(jīng)足夠多了麦乞,但是它卻不能很明確地表示int是4個(gè)字節(jié),long long是8個(gè)字節(jié)劝评,short是2個(gè)字節(jié)姐直。為了解決這些問(wèn)題,c99引入可選名字集合蒋畜,以確定描述信息声畏,前提是引用頭文件inttype.h。例如:int16_t表示一個(gè)16位有符號(hào)整數(shù)類型,uint32_t表示一個(gè)32位無(wú)符號(hào)整數(shù)類型插龄。
除了限制字長(zhǎng)和有無(wú)符號(hào)愿棋,它還包含其他特性。速度特性均牢,如:int_fast8_t糠雨。最小長(zhǎng)度特性,如:int_least8_t徘跪。最大最小峰值甘邀,如:intmax_t和uintmax_t分別表示最大有符號(hào)整數(shù)和最大無(wú)符號(hào)整數(shù)。為打印提供的特定宏真椿,如PRId16打印16位有符號(hào)值等鹃答。
五、浮點(diǎn)類型
c語(yǔ)言中突硝,浮點(diǎn)類型包括:float测摔、double、long double解恰。而為了表示很大和很小的數(shù)锋八,科學(xué)家研究出了科學(xué)計(jì)數(shù)法,例如:123.00使用1.23e2或1.23E2表示护盈。e或E表示10的冪挟纱。如果系統(tǒng)支持c99的十六進(jìn)制格式浮點(diǎn)數(shù),則可以使用a或A代替e或E
浮點(diǎn)數(shù)的表示腐宋,一般使用以下格式表示:
[+|-] | [小數(shù)點(diǎn)前] | [小數(shù)點(diǎn).] | [小數(shù)點(diǎn)后] | [e|E + 整數(shù)表示10的冪]
float和double的打印使用%f紊服,long double使用%Lf,科學(xué)計(jì)數(shù)法使用%e胸竞。例如%e欺嗤、%f、%Lf卫枝、%Le煎饼、%La
#include <stdio.h>
int main(void)
{
float a = 33.234;
printf("%%a is %a %%e is %e\n", a, a);
return 1;
}
輸出如下:
zhangfb@zhangfb-pc:~/workspace/formal/c/first$ gcc two.c
zhangfb@zhangfb-pc:~/workspace/formal/c/first$ ./a.out
%a is 0x1.09df3cp+5 %e is 3.323400e+01
浮點(diǎn)數(shù)和整數(shù)都存在上溢和下溢的問(wèn)題,如:兩個(gè)很大的數(shù)相加校赤,超出實(shí)際能表示的最大數(shù)吆玖。浮點(diǎn)數(shù)和整數(shù)又不太一樣,浮點(diǎn)數(shù)存在精度的問(wèn)題马篮,兩個(gè)浮點(diǎn)數(shù)相乘沾乘,可能出現(xiàn)實(shí)際的值和數(shù)學(xué)計(jì)算出的值不一致的情況,例如3.33*2.333333积蔚,使用數(shù)學(xué)方法計(jì)算得出7.76999889意鲸,但是float在某些系統(tǒng)上最大的精度為6,也就是說(shuō)只能表示小數(shù)點(diǎn)后6位,這時(shí)怎顾,最后兩位89就會(huì)丟失读慎。
六、復(fù)數(shù)和虛數(shù)
這兩種類型槐雾,用得最多的是科學(xué)和工程領(lǐng)域夭委,所以暫時(shí)不做說(shuō)明。
總結(jié)
這兒募强,我以條例的方式株灸,列出一些日常容易犯的錯(cuò)誤和一些好的建議。
1擎值、使用和類型相匹配的聲明
int a = 3; // 推薦寫(xiě)法
int b = 3.3; // 應(yīng)避免寫(xiě)法
int cost = 33.98; // 應(yīng)避免寫(xiě)法慌烧,C會(huì)簡(jiǎn)單地舍棄小數(shù)點(diǎn)及其后面部分,而非四舍五入
float alpha = 32.3323499; // 應(yīng)避免寫(xiě)法鸠儿,float精度為6屹蚊,所以會(huì)舍棄掉最后一位
2、類型前綴
一些有經(jīng)驗(yàn)的程序員會(huì)有自己的變量命名規(guī)范进每,例如int類型的變量名為i_開(kāi)頭汹粤,unsigned short類型的變量名以u(píng)s_開(kāi)頭。這種方式無(wú)分好壞田晚,因人而異嘱兼,比如在Java語(yǔ)言中,推薦變量名中不加入類型前綴贤徒。而C語(yǔ)言是推薦這種命名方式芹壕。
3、輸入輸出函數(shù)的變量個(gè)數(shù)確定
調(diào)用scanf和printf函數(shù)時(shí)接奈,因?yàn)閰?shù)個(gè)數(shù)不固定哪雕,編譯器不會(huì)檢查個(gè)數(shù)和格式是否匹配,如果少寫(xiě)或多寫(xiě)了一些參數(shù)鲫趁,會(huì)出現(xiàn)一些讓人意外的情況。例如:
int a = 3;
float b = 33.2343;
int c, d;
printf("a is %d and b is %.2f\n", a);
printf("a is %d\n", a, b);
printf("please input c.\n");
scanf("%d", &c, &d);
printf("c is %d\n", c);
4利虫、類型長(zhǎng)度規(guī)范
整數(shù)類型:short <= unsigned short <= int <= unsigned int <= long <= unsigned long <= long long <= unsigned long long
浮點(diǎn)類型:float <= double <= long double