本節課理論知識較多。
- C語言有哪些數據類型?有哪些整數類型?有哪些浮點類型?
- 各種數據類型如何表示?輸入輸出格式化有哪些?
- 各種類型大小是多少?范圍是多少?
- 如何選擇整型類型和浮點類型?
1. 數據類型
學習是一個日積月累的過程,從多模仿,到多看多想,最后到多用。
數值類型分為整型(整數)和浮點型(小數)。按照表示數字范圍的從大到小
- 整數分為五類:字符型(
char
)、短整型(short
)、整型(int
)、長整型(long
)和長長整型(long long
) - 浮點型分三類:單精度型(
float
)、雙精度型(double
)和長雙精度型(long double
)
1.1 獲取類型大小
關鍵字sizeof
:查看變量或者類型大小
int n;
printf("%d",sizeof(int));
printf("%d",sizeof(n));
上面的括號不是必須的,但是建議帶上。所以也可以如下表示:
int n;
printf("%d",sizeof int);
printf("%d",sizeof n);
2.2 各種類型的大小
printf("sizeof(char)=%d\n",sizeof(char));
printf("sizeof(short)=%d\n",sizeof(short));
printf("sizeof(int)=%d\n",sizeof(int));
printf("sizeof(long)=%d\n",sizeof(long));
printf("sizeof(long long)=%d\n",sizeof(long long));
printf("sizeof(float)=%d\n",sizeof(float));
printf("sizeof(double)=%d\n",sizeof(double));
printf("sizeof(long double)=%d\n",sizeof(long double));
在編譯命令加上選項-m32
再試一下。
通常有些類型大小并不是固定的,計算機硬件、操作系統和編譯器都會影響類型的大小。通常類型大小有如下規律:
char < short < int < float < double
int <= long <= long long
在常用的計算機硬件和操作系統中,各種類型的大小如下表所示:
2.3 字節
sizeof
獲得數據的單位是Byte(字節)。Byte(字節)是計量存儲容量的一種計量單位,一個字節是8位二進制,可容納256個數字。一個ASCII字符就是一個字節。
除了Byte(字節),還有其他常用存儲容量單位
No. | 單位 | 說明 |
---|---|---|
1 | bit(比特/位) | 計算機中的最小數據單位,1個Byte(字節)=8個bit(比特/位) |
2 | word(字) | 計算機CPU一次操作處理實際數據最大位數,我們常說的32/64位就是計算機的字。 |
3 | KB | 1KB=1024B |
4 | MB | 1MB=1024KB |
5 | GB | 1GB=1024MB |
6 | TB | 1TB=1024GB |
有時,我們用
B
表示Byte(字節),用b
表示bit(比特/位),注意兩者區別。
2.4 輸入輸出格式化
No. | 類型 | 占位符 |
---|---|---|
1 | char |
%c |
2 | short |
%hd |
3 | int |
%d |
4 | long |
%ld |
5 | long long |
%lld |
6 | float |
%f |
7 | double |
%lf |
8 | long double |
%Lf |
double
的輸入占位符必須是%lf
,輸出占位符可以是%f
。
2. 整數類型
2.1 表示范圍
每種數據類型大小不同,各自表示數據范圍也不同。下面的常用類型的范圍。
No. | 類型 | 數字范圍 | 表示 |
---|---|---|---|
1 | char |
-128 ~127
|
-27~27-1 |
2 | short |
-32 768 ~32 767 約 |
-215~215-1 |
3 | int |
-2 147 483 648 ~2 147 483 647 約 |
-231~231-1 |
4 | long long |
-9 223 372 036 854 775 808 ~9 223 372 036 854 775 807 約 |
-263~263-1 |
上面的是通常范圍(32位下),實際上有些情況略有出入。總之,類型的表示范圍與類型大小存在如下關系:
其中,是類型大小。
2.2 無符號整型
在一些特殊情況下,數據只用0
和整數,不存在負數,這時可以使用無符號整型unsigned
。無符號整型只是在原來的整型前加上關鍵字unsigned
。因為沒有負數,所以數值的表示范圍擴大了一倍。
No. | 類型 | 數字范圍 | 表示 |
---|---|---|---|
1 | unsigned char |
0 ~255
|
0~28-1 |
2 | unsigned short |
0 ~65 535 約 |
0~216-1 |
3 | unsigned int |
0 ~4 294 967 295 約 |
0~232-1 |
4 | unsigned long long |
0 ~18 446 744 073 709 551 615
|
0~264-1 |
類型的表示范圍與類型大小存在如下關系:
其中,是類型大小。
輸入輸出無符號整型格式
No. | 類型 | 占位符 |
---|---|---|
1 | char |
%u |
2 | short |
%hu |
3 | int |
%u |
4 | long |
%lu |
5 | long long |
%llu |
2.3 整型類型選擇
整型類型很多,通常遵循下面的使用規則:
- 大多數情況下使用
int
。 - 如果
int
范圍不夠,使用long long
。 - 避免使用
long
。 - 謹慎使用
unsigned
。
3. 浮點類型
3.1 浮點數的范圍
運行下面程序,分析執行結果:
#include <stdio.h>
int main(){
printf("1.0/0.0 = %f\n",1.0/0.0);
printf("-1.0/0.0 = %f\n",-1.0/0.0);
printf("0.0/0.0 = %f\n",0.0/0.0);
return 0;
}
當浮點數超出可表示的范圍,會有如下值。
No. | 輸出 | 含義 |
---|---|---|
1 | inf |
表示正無窮大 |
2 | -inf |
表示負無窮大 |
3 | nan |
不存在 |
3.2 浮點數的精度
- 設計上的精度問題
運行下面程序,分析執行結果:
#include <stdio.h>
int main(){
float f = 123456789.0;
double d = 123456789.0;
printf("f=%f\n" ,f);
printf("d=%lf\n",d);
return 0;
}
計算機浮點數存在精度問題。
No. | 類型 | 數字范圍 | 有效數字 |
---|---|---|---|
1 | float |
-3.4E+38 ~3.4E+38
|
6~7 |
2 | double |
-1.7E-308 ~1.7E+308
|
15~16 |
3 | long double |
-1.2E-4932 ~1.2E+4932
|
18~19 |
注意:浮點類型沒有無符號unsigned
類型。
- 運算中的精度問題
運行下面程序,分析執行結果:
#include <stdio.h>
int main(){
float a = 10.2;
float b = 9;
float c = a - b;
printf("%f - %f = %f\n", a,b,c);
return 0;
}
上面結果看似正確,把程序改成如下:
#include <stdio.h>
int main(){
float a = 10.2;
float b = 9;
float c = a - b;
if(c == 1.2){
printf("%f == 1.2",c);
}else{
printf("%f != 1.2",c);
}
return 0;
}
以7位有效數組打印運算結果。
#include <stdio.h>
int main(){
float a = 10.2;
float b = 9;
float c = a - b;
printf("%.7f - %.7f = %.7f\n", a,b,c);
return 0;
}
發現運算中存在精度缺失。
如何比較浮點數?使用最小誤差。
#include <stdio.h>
int main(){
float a = 10.2;
float b = 9;
float c = a - b;
if(fabs(c - 1.2) < 0.000001){
printf("%f == 1.2\n",c);
}else{
printf("%f != 1.2\n",c);
}
return 0;
}
在誤差范圍內認為相等。即絕對值差小于精度最小值。
float
浮點數誤差通常為(6位有效數字)。
double
浮點數誤差通常為(15位有效數字)。
3.3 浮點類型選擇
浮點類型有三種,通常遵循下面的使用規則:
- 大多數情況下使用
double
。 - 盡量不要使用
float
。 - 過程運算可以使用
long double
。
問題
- 既然浮點數這么不準確,為什么還需要?
浮點數通過損失精度,獲取更大的表示范圍。 - 試一試:整數除以零會有什么結果
#include <stdio.h>
int main(){
printf("1/0 = %d\n",1/0);
return 0;
}
4. 字符類型
字符類型是一個特殊類型,是整型的一種。使用單引號表示字符字面量,例如:字母'a'
、數字'1'
、空字符''
、轉義字符\n
。
通常使用%c
作為格式化占位符輸入輸出,有時也可以使用%d
輸出字符對應ASCII編碼。
- 打印字符
#include <stdio.h>
int main(){
char c='1';
printf("%c\n%d\n",c,c);
return 0;
}
4.1 ASCII編碼
ASCII編碼使用7 位二進制數(剩下的1位二進制為0)來表示所有的大寫和小寫字母,數字0 到9、標點符號, 以及在美式英語中使用的特殊控制字符。
ASCII表的特點:
- 字母在ASCII表中是順序排列的。
- 大寫字母和小寫字母是分開排列的。
C語言中字符即數字。
printf("%d\n",'a'); printf("%c\n",97);
4.2 運算
- 字符類型可以像整型一樣參與運算。
例如:
#include <stdio.h>
int main(){
char a='a';
printf("%c\n%c\n",a,a+1);
return 0;
}
字符類型操作含義:
- 一個字符加上一個數字得到ASCII表中對應新字符。
- 兩個字符相減,得到這兩個字符在表中的距離。
實例:
- 分別打印出26個大寫字母和小寫字母。
- 把一個字符串整型數字轉化成整型數字。例如:
"1234"
轉發成1234
。 - 判斷一個字符串是否存在滿足標識符命名規則。
- 大小寫轉換
4.3 轉義字符/逃逸字符
在ASCII表中,除了常見的字符(如:大小寫字母、數字等),還包含一些無法打印出來的控制字符或特殊字符。這些字符以反斜線\
開頭,后面接著一個字符,這種字符被稱作轉義字符/逃逸字符。
- 常用的轉義字符/逃逸字符
字符 | 含義 | 字符 | 含義 |
---|---|---|---|
\' |
單引號 | \" |
雙引號 |
\r |
回車 | \n |
換行 |
\b |
退格符 | \f |
翻頁符 |
\t |
表格符 | \\ |
反斜線符 |
5. 布爾類型
在C99中新增bool
類型表示邏輯值,它只有兩種值(true
和false
)。使用前需要加上頭文件stdbool.h
。
6. 數據轉換
6.1 自動類型轉換
當運算符左右兩邊操作數的類型不一致時,會自動轉換成較大類型。
- 整型:
char
→short
→int
→long
→long long
- 浮點型:
int
→float
→double
→long double
6.2 強制類型轉換
當把一個較大的類型轉換成較小的類型,需要強制轉換。
強制轉換語法
(轉換后的類型)值
例如:
printf("%d\n",(int)3.14);
有時,整型轉浮點型也需要強制轉換。
例如:
printf("%f\n",(double)1/2);
其中,浮點數轉整數采用的是截斷方式。
7.練習
- 下面代碼輸出結果
int main(){
for(char i =0; i < 256; ++i){
printf("%d\n", i);
}
}