/**
二進位制
賦值時以 0b 或 0B 開頭;
輸出時沒有所屬預留位置, 十六進位制整數輸出也比較直觀
*/
int num_bin = 0b110;
printf("%d\n", num_bin); // 以十進位制整數形式輸出
//其他進位制輸出形式略,總之就是沒有二進位制形式的輸出
/**
八進位制
賦值時以0(零)開頭;
預留位置:%o (小寫字母o , 八進位制整數)
*/
int num_oct = 0123;
printf("%o\n", num_oct); // 以八進位制整數形式輸出
/**
十進位制
賦值時正常表示
預留位置:%d 表示輸出形式為十進位制整數
*/
int num_deci = 123456;
printf("%d\n", num_deci);
/**
十六進位制
以0x或0X開頭
預留位置: %x 輸出十六進位制整數(A-F輸出為小寫)
%X 輸出十六進位制整數(A-F輸出為大寫)
%#x 輸出0x樣式十六進位制整數
%#X 輸出0X樣式十六進位制整數
*/
int num_hex = 0xff;
printf("%x\n", num_hex);
printf("%#x\n", num_hex);
printf("%#X\n", num_hex);
拓展問題:有沒有浮點型別二/八/十六進位制的數的展示 ?輸出呢?
似乎有,似乎用處不大。來一段:
float hex_float = 0x1P3;
printf("hex_float = %f\n", hex_float); // 輸出為 hex_float = 8.000000
在這裡,0x1P3
是一種用科學計數法表示十六進位制浮點數的方式。在這個例子中,1P3
表示1乘以2的3次方,也就是8。
原碼:最高位表示符號位(0正、1負)的機器數。
反碼:正數反碼即原碼;負數反碼符號位不變,其他位取反。
反碼存在的意義就是為了求二補數。
二補數:正數的二補數即原碼;負數的二補數即反碼+1。
二補數存在的意義就是為使計算機運算更方便,因為計算機沒有設計減法器,聽說減法器不如用二補數更簡潔和高效。
二補數的設計原理是:讓負數原碼的絕對值和負數的二補數相加為全零(最高位溢位),這個補全後的數即為該儲存大小能表示的個數,2位元組的話這個數即為65536,這樣的話有效位數就全為0了。
比如:2+(-2)=0。 -2的二補數離有效位全0少2;+2離有效位全0多了2,對於有效位全0來說剛好互補。
這樣設計的好處為:作減法運算時,可視為正數和負數相加。
運算時,符號位也參與運算。
負數二補數轉原碼時,也可以直接取反後+1得到。
/**
下面的程式碼中
short 佔兩個位元組,能表示65536個數,最高位溢位,有效位全0
-2的在記憶體中以二補數形式儲存,表示為十進位制即為65534,要用%u輸出
也可以想-2離有效位全0即65536少2,即65534
*/
unsigned short num_byte2 = -2;
printf("%hu\n", num_byte2); // 輸出為 65534 hu表示無符號短整型
short num_byte2_1 = -2;
printf("%hu\n", num_byte2_1); // 輸出為 65534
問題:參考上面的程式碼,下面的程式碼為什麼會這樣子輸出?
unsigned short num_byte2 = -2; // 這一步將num_byte2轉換為65534
printf("%u\n", num_byte2); // 輸出為 65534
short num_byte2_1 = -2; // 在這一步num_byte2_1還是-2
printf("%u\n", num_byte2_1); // 輸出為 4294967294 轉換為無符號時short佔不下了,按四個位元組來,就變成了 4294967296-2, 即 4294967294
整型
短整型 short ---------- 2Byte
有符號短整型 signed short / short 預留位置為: %hi 表示範圍:-32768到32767 字面量無尾綴
無符號短整型 unsigned short 預留位置為: %hu 表示範圍:0到65535 字面量無尾綴表示
整型 int ---------- 16位元機 2Byte; 32位元機 4Byte
有符號整型 signed int / int 預留位置: %d 表示範圍: 根據位數決定
一般拼寫上一個沒超過int範圍的數預設字面量的型別為int,除非在字面量後面加尾綴。
無符號整型 unsigned int 預留位置 %u 表示範圍: 根據位數決定 字面量尾綴為u或U
長整型 long ----------- 32位元機 4Byte; 64位元機 8Byte 問題: 我64位元機咋還是4Byte? windows的問題。Linux就是8個。不同系統使用的資料模型不同,導致long表示的範圍不能確定無二。
有符號長整型 signed long / long 預留位置:%ld 表示範圍:不做掌握 字面量尾綴 l或L
無符號長整型 unsigned long 預留位置: %lu 表示範圍:不做掌握 字面量尾綴lu或ul
長長整型 long long ------------ 8Byte
有符號長長整型 signed long long / long long 預留位置: %lld 表示範圍:很大很大 字面量尾綴ll或LL
無符號長長整型 long long 預留位置: %llu (l和u位置不可互換) 表示範圍:很大很大 字面量尾綴llu或LLU
注意:
任何系統的pointer(指標型別)位數和系統一致,比如64位元即8Byte;
char、int、long long不隨系統改變;
儘量不使用long;
想確保int為4Byte可以使用stdint.h庫裡的 int32_t 型別
浮點型
單精度浮點型 float --------- 4Byte
表示範圍:1.2E-38 到 3.4E+38
字面量尾綴f或F,給不加小數點的字面常數尾綴f或F會報錯
預留位置:對於printf(...)來說,單精度和雙精度都是 %f
雙精度浮點型 double --------- 8Byte
表示範圍 2.3E-308 到 1.7E+308
加了小數點的字面量預設為double,無需尾綴
預留位置:對於printf(...)來說,單精度和雙精度都是 %f
長雙精度浮點型 long double ------------ 32位元機 10Byte; 64位元機16Byte
表示範圍 很大很大
字面量尾綴l或L,給不加小數點的字面常數尾綴f或F會表示為long
預留位置:%Lf
浮點數列印時預設保留六位小數,可自行調整。如下:
double num_doub = 123456789.23956;
// 注意: 這個保留的兩位是四捨五入而不是擷取 (我用的gcc,別的編譯器沒試過)
printf("%20.2lf\n", num_doub); // 總共輸出二十個字元,不夠前面補空格。小數點後保留兩位,如果整數位大於二十,則仍然完整輸出整數位,小數位保留兩位(注意.2後面是字母l,不是數位1)
// %e 預留位置可以輸出浮點數的科學計數法表示形式(適用float和double) 長雙用%Le(L大寫)
double num_double2 = 123.4;
printf("%e\n", num_double2);
字元型 char ------- 1Byte
預留位置: %c
不能存中文字元,想存中文字元用指標或陣列。
本質就是一個整數。不同裝置把char預設為有符號/無符號的型別。一般是有符號,即 -128 到 127
布林型 _Bool
隱式轉換(自動型別轉換)
short(2)/ char(1) ----> int(2/4) -----> unsigned int (2/4) --------> long(4/8) ------> unsigned long(4/8) ----> long long(8) ------> float(4) ------> double(8) ------> long double(10/32)
浮點轉整型有可能出現溢位(如果整數很大)或者 精度缺失
顯示轉換(強制型別轉換,略) 整數小轉大具體細節按二補數計算。涉及浮點數的小轉大不會。
float num_f = 12.3f;
double num_dou = (double) num_f;
printf("%lf\n", num_dou); // 輸出 12.300000
sizeof(型別/變數名/字面量/表示式)
如果不是檢視 型別或表示式 的大小,可以使用 sizeof 變數名/字面量
預留位置為 %zu 或 %d
返回型別為size_t,根據系統決定實際型別。
返回型別的位元組個數,如果檢視某個字面量的位元組佔用個數,查的是它預設的使用型別位元組數。
\b 退格; \n 換行符; \r 回車符; \t 製表符; \加單雙引號或斜槓在特殊情況下跳脫為它們本身等
#include<stdio.h>
#include<stdint.h>
// 精確寬度整數型別
// 64位元,很多計算機底層為long long , %d 輸出會數值錯亂
int64_t e1 = 4500000000;