01-進制轉(zhuǎn)換-基本概念
如何輸出十進制 %i %d, 以十進制的方式輸出數(shù)據(jù)
在編程中想表示二進制,需要在數(shù)字前面加上0b
%o 就是以八進制的形式輸出
在編程中想表示八進制,需要在數(shù)字前面加上0
%x 就是以十六進制的形式輸出
在編程中想表示十六進制,需要在數(shù)字前面加上0x
注意: 在C語言中沒有以二進制輸出的占位符
02-進制轉(zhuǎn)換
1.十進制 轉(zhuǎn) 二進制
規(guī)律 : 用需要轉(zhuǎn)換的十進制 除以2 取余數(shù) , 然后倒數(shù)
13 / 2 = 6 余 1
6 / 2 = 3 余 0
3 / 2 = 1 余 1
1 / 2 = 0 余 1
-------- = 1101
2. 二進制 轉(zhuǎn) 十進制
規(guī)律 : 從低位數(shù)開始, 用低位 乘以 2的 多少次冪, 冪數(shù)從0開始,然后再相加
二進制 : 1101
1 * 2(0) = 1
0 * 2(1) = 0
1 * 2(0) = 4
1 * 2(3) = 8
1 + 0 + 4 + 8 = 13
口訣
1 1 1 1
8 4 2 1
3. 二進制 轉(zhuǎn) 八進制
規(guī)律 : 三個二進制位 代表一個八進制位, 只需要將3個二進制位 轉(zhuǎn)換為十進制, 之后再將所有的結(jié)果連接起來
1001 轉(zhuǎn)換為 00 001 001
0 1 1
------------------------
011 == 0 * 8 + 1 * 8 + 3 = 11(十進制)
4. 二進制 轉(zhuǎn) 十六進制
規(guī)律 : 四個二進制位代表一個十六進制位, 只需要將4個二進制位轉(zhuǎn)換成10進制, 之后再將所有的結(jié)果連接起來
0001 1011
--------
1 b = 0x1b
03-原碼補碼反碼
為什么要有 原碼 / 反碼 / 補碼 ? 主要是為了方便計算機計算
其實二進制的第一位 是二進制的符號位
如果該位是0 代表這個數(shù) 是正數(shù)
如果該位是1 代表這個數(shù) 是負數(shù)
正數(shù)
總之一句話, 正數(shù)的原碼\補碼\反碼 都是一樣的,三碼合一
負數(shù)
反碼 : 符號位不變, 其他位取反(0變1,1變0)
補碼 : 反碼 + 1就是補碼
9的二進制
正數(shù)
0000 0000 0000 0000 0000 0000 0000 1001 (原碼)/反碼/補碼
負數(shù)
1000 0000 0000 0000 0000 0000 0000 1001 (原碼)
1111 1111 1111 1111 1111 1111 1111 0110 (反碼)
1111 1111 1111 1111 1111 1111 1111 0111 (補碼)
// 補碼的深入
1 - 1 = 1 + (-1)
原碼 計算結(jié)果 = -2
反碼 計算結(jié)果 = -0
補碼 計算結(jié)果 = 0
04-位運算
位運算 (和二進制相關(guān))
1.& 按位與
規(guī)律 : 一假則假, 1真 0假
規(guī)律 : 任何數(shù)和 1 相& 得到的結(jié)果還是那個數(shù)
1001 & 1111 = 1001
2.| 按位或
規(guī)律 : 一真則真
3.^ 按位異或
重點 : 異或的結(jié)果 和 參與運算的順序沒有關(guān)系
規(guī)律1 : 不相同為1, 相同為0 (異或)
1001 ^ 0101 = 1100
規(guī)律2 : 相同的兩個數(shù) 異或 等于0
5 ^ 5 = 0101 ^ 0101 = 0
規(guī)律3 : 任何數(shù) 和 0 異或上0 結(jié)果不變
5 ^ 0 = 0101 ^ 0000 = 0101 = 5
規(guī)律4 : 任何一個數(shù) 異或上 同一個數(shù)兩次, 結(jié)果不變
9 ^ 5 ^ 5 = ? == 9 ^ 0 = 9
~ 取反
計算機是以補碼形式存在的
1.先拿到數(shù) 的原碼 [進行一個取反] 在 -1 變成反碼 再將反碼 轉(zhuǎn)為原碼
一 . 9 原碼 0000 0000 0000 0000 0000 0000 0000 1001
二 . 取反的得到補碼 -->
1111 1111 1111 1111 1111 1111 1111 0110 的到的補碼
三 . 再將 補碼 -1變成反碼 -->
1111 1111 1111 1111 1111 1111 1111 0101
四 . 再將反碼取反變回原碼 --->
1000 0000 0000 0000 0000 0000 0000 1010 == -10
~9 = -10
原碼 --> 反碼(取反) -->(補碼)+1
補碼 --> 反碼(-1) --> 原碼(取反)
05-左移右移
左移 <<
規(guī)律 : 左移 就是左移的數(shù)乘以2的移動次冪
例如
9 << 1 = 9 * 2(1) = 18
9 << 2 = 9 * 2(2) = 36
注意點 :
由于左移運算,被移動的數(shù) 最高位會被拋開(移除),所以左移有可能會改變一個數(shù)的正負性
右移 >>
規(guī)律 : 右移 就是右移的數(shù)除以2的移動次冪
9 >> 1 = 9 / 2(1) = 4;
9 >> 1 = 9 / 2(2) = 2;
注意 : 負數(shù)的左移右移 是補碼在移動,因為負數(shù)都是以補碼的形式存儲在內(nèi)存中的
應(yīng)用場景 : 如果想讓某一個數(shù) 乘以2的多少次冪,或者除以2的多少次冪,最高運算方式就是左移右移
06-位運算-練習1
使用按位與 &
任何數(shù)和 1 相& 得到的結(jié)果還是那個數(shù)
0000 0000 0000 0000 0000 0000 0000 1001
&0000 0000 0000 0000 0000 0000 0000 0001
----------------------------------------
// 1.讓9的二進制向右移31位,就可以獲取到9的最高位的二進制,然后讓9的二進制的最高位 和1相與,那么就可以獲得9的最高位
// 2.讓9的二進制向右移動30位,就可以獲取9二進制第二位
// 3.以此類推,直到0位置
技巧
1.任何數(shù) 與 1相& 都是那個數(shù)
2.利用位移 取出每一位
07-位運算-練習2
1001 9
1010 10
1011 11
1100 12
通過觀察,
我們發(fā)現(xiàn)如果是偶數(shù),那么二進制的最后1位是0,
如果是奇數(shù),那么二進制的最后1位是1.
if ((num & 1) == 1) {
printf("奇數(shù)");
}
else
{
printf("偶數(shù)\n");
}
08-位運算-練習3
/*
不相同為1, 相同為0 (異或)
*/
/*
a = a ^ b;
b = a ^ b; // a ^ b ^ b = a ^ 0 = a
a = a ^ b; // a ^ b ^ a = b ^ 0 = b
*/
#pragma 開發(fā)簡單加密
// 用戶密碼, 純數(shù)字
int pwd = 123;
// 對用戶密碼 進行簡單加密
int result = pwd ^ 456;
// 對用戶密碼進行解密
result = result ^ 456;
09-變量內(nèi)存分析
主要定義變量, 系統(tǒng)就會開辟一塊存儲空間 給我們的變量存儲數(shù)據(jù),內(nèi)存尋址是從大到小
越先定義的變量,內(nèi)存地址越大
注意 : 由于內(nèi)存尋址是從大到小, 所以存儲數(shù)據(jù)也是從大到小的存儲(先存儲二進制的高位,再存儲低位)
高位 --> 低位
0000 0000 0000 0000 0000 0000 0000 1001
10-char類型-基本概念
計算機只能識別0和1 'a' 通過ASCII碼表 獲取一個值 轉(zhuǎn)換成二進制
在C語言中, 不看怎么存, 只看怎么取
char類型 在某些情況下 可以當做整型來用
如果對內(nèi)容要求特別嚴格,而且需要存儲的整數(shù) 不超過char類型的取值范圍,那么就可以使用char類型來代替int類型
-2(7)~2(7) - 1 = -128 ~ 127
char c =128; // 打印出來 -128 因為超出了范圍
11-char類型-練習
大寫 ASCII碼 65 - 90
小寫 ASCII碼 97 - 122
差值 ('a' - 'A') 97 - 65 = 32;
12-類型說明符
類型說明符:
1.說明長度的 (它可以用于修改 類型 所占用的存儲空間的大小)
short;
輸出 %hi hd // 2個字節(jié) == -2(15)~2(15)-1
long;
輸出 %li ld // (64位占8個字節(jié)) 32 位long 占用4個字節(jié) , long long 占用 8個字節(jié) == -2(63) ~ 2(63)-1
long long;
輸出 %lli %lld // 8個字節(jié) == -2(63) ~ 2(63)-1
用于說明數(shù)據(jù)類型, 一般情況下 和 int 配合使用
2.說明符號位 (它可以用于修改符號位)
unsigned; (無符號) 輸出 %u . 取值 整數(shù) 和 零
signed; (有符號的) 取值 正數(shù) 和 零 以及 負數(shù)
如果給變量加上修飾符 signed 代表當前變量的取值可以是 正數(shù) / 負數(shù) /零
如果給變量加上修飾符 signed 就代表把 二進制的最高位作為符號位
而且默認情況下所有變量都是有符號的(signed)
3.不同類型的說明符 可以混合使用
unsigned short
signed long
注意 : 相同類型的 說明符 不能同時在一起使用
13-數(shù)組-基本概念
/*
數(shù)組的定義格式 :
數(shù)據(jù)類型 變量名稱;
數(shù)據(jù)類型 數(shù)組名稱[數(shù)據(jù)的個數(shù)];
元素類型 數(shù)組名稱[元素個數(shù)];
元素類型:就是數(shù)組中需要存儲的數(shù)據(jù)類型 , 一旦確定, 數(shù)組中就只能存儲該類型的數(shù)據(jù)
元素個數(shù): 就是數(shù)組中能夠存儲的數(shù)據(jù)(元素)的個數(shù)
*/
14-數(shù)組-初始化
數(shù)組的部分\完全初始化
部分初始化 [1)默認從0開始初始化 -- 2)如果"在部分初始化中",對應(yīng)的內(nèi)存沒有被初始化, 那么默認是0]
int scores1[3] ={11,22};
完全初始化 [1) 依次將{}中的每一個值 賦值給數(shù)組中的每一個元素 -- 2)并且從0開始賦值]
int scores[5] = {99,88,77,66,100};
注意1:如果沒有對數(shù)據(jù)進行初始化(完全和部分),那么不要隨便使用數(shù)組中的數(shù)據(jù),可能是一堆垃圾數(shù)據(jù)(隨機值)
int scores2[3]; // 0 = 32767 1 = 0 2 = 0
注意2: 定義數(shù)組的時候,數(shù)組的元素個數(shù)不能使用變量,如果使用變量,那么數(shù)組中 是一些隨機值
int num = 3; int scores3[num]; // 0 = 1606416240 1 = 32767 2 = 3611
(報錯)注意3: 不建議使用變量定義數(shù)組,如果使用了變量定義數(shù)組, 作為數(shù)組的元素個數(shù),不初始化的情況下是隨機值,如果初始化會直接報錯
int num1 = 3;int scores4[num1] = {11,12};
注意4: 如果定義的同時進行初始化,那么元素的個數(shù)可以省略
省略之后, 初始化賦值幾個數(shù)據(jù),那么數(shù)組的長度就是幾,也就是說數(shù)組將來就能存儲 幾個數(shù)據(jù)
int scores5[] = {1,3};
(報錯)注意5: 如果定義數(shù)組時沒有進行初始化, 那么不能省略元素個數(shù)
int scores6[];
可通過[索引] = 的方式, 給指定索引的元素賦值
int scores7[101] = {[99]=1,[100]=5};
(報錯)注意6: 只能在定義的同時 利用{}進行初始化,如果是先定義 那么就不能使用{}進行初始化
如果先定義 那么就不能再進行整體賦值, 只能單個賦值
int scores8[3];
scores8 = {1,3,4};
15-數(shù)組-遍歷
// 注意 : 在遍歷數(shù)組的時候, 盡量不要把遍歷的次數(shù)寫死
// 遍歷多少次應(yīng)該 由數(shù)組來決定 , 也就是說遍歷多少次 應(yīng)該通過數(shù)組計算得出
/*
printf("scores = %lu\n",sizeof(scores)); // 計算出數(shù)組中占用的總字節(jié)數(shù)
printf("socre[0] = %lu\n",sizeof(scores[0])); // 計算出數(shù)組中某一個元素占用的字節(jié)數(shù)
printf("一個有多少個元素 : %lu\n",sizeof(scores) / sizeof(scores[0]));
*/
// 動態(tài)計算數(shù)組的元素個數(shù)
int length = sizeof(scores) / sizeof(scores[0]);