-
進(jìn)制
二進(jìn)制以0b或0B開頭蒲牧,如0b001。(數(shù)字0不是字母O)
八進(jìn)制以0開頭嘁捷,如067造成。
十六進(jìn)制以0x或0X開頭,如0x48B雄嚣。
-
打印一個數(shù)的八進(jìn)制和十六進(jìn)制:
int a = 13; printf("10->8: %o\n", a); printf("10->16: %x\n", a);
-
定義一個二進(jìn)制數(shù)晒屎、八進(jìn)制數(shù)喘蟆、十六進(jìn)制,打印其對應(yīng)的10 進(jìn)制
int a = 0b00000000000000000000000000001101; printf("2->10: %d\n", a); a = 015; printf("8->10: %d\n", a); a = 0xd; printf("16->10: %d\n", a); 輸出結(jié)果: 2->10: 13 8->10: 13 16->10: 13
進(jìn)制轉(zhuǎn)換
-
原碼,反碼鼓鲁,補碼
正數(shù)的原碼蕴轨,反碼,補碼都一樣骇吭。三碼合一橙弱。
負(fù)數(shù)的第一位為符號位,反碼是原碼取反燥狰,補碼是反碼加一棘脐。
正數(shù)和負(fù)數(shù)在計算機的內(nèi)存中都以補碼的形式存在。
對于負(fù)數(shù), 補碼表示方式也是人腦無法直觀看出其數(shù)值的龙致。 通常也需要轉(zhuǎn)換成原碼在計算其數(shù)值蛀缝。
-
為什么要引入反碼和補碼?
現(xiàn)在我們知道了計算機可以有三種編碼方式表示一個數(shù). 對于正數(shù)因為三種編碼方式的結(jié)果都相同, 所以不需要過多解釋。
但是對于負(fù)數(shù), 可見原碼, 反碼和補碼是完全不同的. 既然原碼才是被人腦直接識別并用于計算表示方式, 為何 還會有反碼和補碼呢?
首先, 因為人腦可以知道第一位是符號位, 在計算的時候我們會根據(jù)符號位, 選擇對真值區(qū)域的加減目代。但是對于計算機, 加減乘數(shù)已經(jīng)是最基礎(chǔ)的運算, 要設(shè)計的 盡量簡單. 計算機辨別"符號位"顯然會讓計算機的基礎(chǔ)電路設(shè)計變得十分復(fù)雜! 于是人們想出了 將符號位也參與運算的方法. 我們知道, 根據(jù)運算法則減去一個正數(shù)等于加上一個負(fù)數(shù), 即: 1-1 = 1 + (-1) = 0 , 所以機器可以只有加法而沒有減法, 這樣計算機運算的設(shè)計就更簡單了.
-
例:
計算十進(jìn)制的表達(dá)式: 1-1=0
1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2
如果用原碼表示, 讓符號位也參與計算, 顯然對于減法來說, 結(jié)果是不正確的.這也就是為何計算 機內(nèi)部不使用原碼表示一個數(shù).
為了解決原碼做減法的問題, 出現(xiàn)了反碼:
1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 (1111 1111,符號位不變,其他為逐位取反) = -0
發(fā)現(xiàn)用反碼計算減法, 結(jié)果的真值部分是正確的. 而唯一的問題其實就出現(xiàn)在"0"這個特殊的數(shù)值 上. 雖然人們理解上+0和-0是一樣的, 但是0帶符號是沒有任何意義的. 而且會有[0000 0000]原和 [1000 0000]原兩個編碼表示0屈梁。
于是補碼的出現(xiàn), 解決了0的符號以及兩個編碼的問題:
1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]補 + [1111 1111]補 = [0000 0000]補 = [0000 0000]原
- 這樣0用[0000 0000]表示, 而以前出現(xiàn)問題的-0則不存在了.而且可以用[1000 0000]表示-128: (-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]補 + [1000 0001]補 = [1000 0000]補
- -1-127的結(jié)果應(yīng)該是-128, 在用補碼運算的結(jié)果中, [1000 0000]補 就是-128. 但是注意因為實際 上是使用以前的-0的補碼來表示-128, 所以-128并沒有原碼和反碼表示.(對-128的補碼表示[1000 0000]補算出來的原碼是[0000 0000]原, 這是不正確的)
-
位運算符
-
& 按位與
規(guī)律:二進(jìn)制中,與1相&就保持原位榛了,與0相&就為0在讶。
-
應(yīng)用場景:
按位與運算通常用來對某些位清0或保留某些位。例如把a的高位都清0霜大,保留低八位构哺,那么就a&255。
判斷奇偶: 將變量a與1做位與運算僧诚,若結(jié)果是1遮婶,則 a是奇數(shù);若結(jié)果是0湖笨,則 a是偶數(shù)。
-
任何數(shù)和1進(jìn)行&操作,得到這個數(shù)的最低位蹦骑。
1001
&0001
=0001
?
-
想把某一位置0慈省。
11111111
&11111011
=11111011
| 按位或
-
^ 按位異或
-
規(guī)律:
- 相同整數(shù)相的結(jié)果是0。比如55=0眠菇。
- 多個整數(shù)相的結(jié)果跟順序無關(guān)边败。比如567=576。因此得出結(jié)論:__ab^a = b__捎废。
-
使用位運算實現(xiàn)交換兩個數(shù)的值:
a = a^b; b = b^a; a = a^b;
-
~ 取反
-
-
左移運算符和右移運算符
把整數(shù)a的各二進(jìn)位全部左移n位笑窜,高位丟棄,低位補0登疗。左移n位其實就是乘以2的n次方排截。由于左移是丟棄最高位嫌蚤,0補最低位,所以符號位也會被丟棄断傲,左移出來的結(jié)果值可能會改變正負(fù)性脱吱。
把整數(shù)a的各二進(jìn)位全部右移n位,保持符號位不變认罩。右移n位其實就是除以2的n次方箱蝠。為正數(shù)時, 符號位為0垦垂,最高位補0宦搬。為負(fù)數(shù)時,符號位為1劫拗,最高位是補0或是補1床三,取決于編譯系統(tǒng)的規(guī)定。
-
例:
寫一個函數(shù)把一個10進(jìn)制數(shù)按照二進(jìn)制格式輸出
-
分析:
13 -----> 0000 0000 0000 0000 0000 0000 0000 1101
0000 0000 0000 0000 0000 0000 0000 1101 13
0000 0000 0000 0000 0000 0000 0000 0001 1
每次取 一個數(shù)的最后一個二進(jìn)制位
任何一個數(shù)和1進(jìn)行&(按位與)得到任何一個數(shù)的二進(jìn)制的最后
一位
-
實現(xiàn):
int len = sizeof(int)*8; int temp; for (int i=0; i<len; i++) { temp = num; //每次都在原數(shù)的基礎(chǔ)上進(jìn)行移位運算 temp = temp>>(31-i); //每次移動的位數(shù) int t = temp&1; //取出最后一位 if(i!=0&&i%4==0)printf(" "); printf("%d",t); }
-
變量的存儲
一個變量所占用的存儲空間杨幼,不僅跟變量類型有關(guān)撇簿,而且還跟編譯器環(huán)境有關(guān)系。同一種類型的變量差购,在不同編譯器環(huán)境下所占用的存儲空間又是不一樣的四瘫。
任何變量在內(nèi)存中都是以二進(jìn)制的形式存儲。一個負(fù)數(shù)的二進(jìn)制形式欲逃,其實就是對它的正數(shù)的二進(jìn)制形式進(jìn)行取反后再+1找蜜。
-
變量的首地址,是變量所占存儲空間字節(jié)地址最小的那個地址。(因為變量的字節(jié)的地址在內(nèi)存中是由大到小的稳析,以0b00000000 00000000 00000000 00001010為例洗做,00001010屬于低字節(jié),位于這個變量所占4個字節(jié)的最上面的那個字節(jié)彰居,也就是地址最小的字節(jié)诚纸。類似Excel中的四個表格,低字節(jié)位于最上面(地址最谐露琛))畦徘。
?
-
類型說明符
在64位編譯器環(huán)境下:
short占2個字節(jié)(16位)
int占4個字節(jié)(32位)
long占8個字節(jié)(64位)
因此,如果使用的整數(shù)不是很大的話抬闯,可以使用short代替int井辆,這樣的話,更節(jié)省內(nèi)存開銷溶握。
ANSI \ ISO制定了以下規(guī)則:
? short跟int至少為16位(2字節(jié))
? long至少為32位(4字節(jié))
? short的長度不能大于int杯缺,int的長度不能大于long
? char一定為為8位(1字節(jié)),畢竟char是我們編程能用的最小數(shù)據(jù)類型
- 32位編譯器:long long 占 8個字節(jié), long 占 4個字節(jié)睡榆。
- 64位編譯器:long long 和 long 都是 8個字節(jié)萍肆。
-
- long long int == long long
- long int == long
- short int == short
?
-
char型數(shù)據(jù)存儲原理
- char a=‘a(chǎn)' ——> 取出'a'的ASCII碼值,97,然后轉(zhuǎn)換2進(jìn)制,存儲在一個字節(jié)中袍榆。
- 個人理解,ASCII表就是為字符設(shè)計的匾鸥,因為字符在內(nèi)存中存儲時首先取出這個字符的ASCII碼值蜡塌,然后轉(zhuǎn)換成二進(jìn)制之后存儲。而且一個字符占一個字節(jié)勿负,所以共8位馏艾,取值范圍是-27~27-1,所以ASCII表也是0~127奴愉。
-
數(shù)組
-
初始化數(shù)組
- int ages[3] = {4, 6, 9};
- int nums[10] = {1,2}; // 其余的自動初始化為0
- int nums[] = {1,2,3,5,6}; // 根據(jù)大括號中的元素個數(shù)確定數(shù)組元素的個數(shù)
- int nums[5] = {[4] = 3,[1] = 2}; // 指定元素個數(shù),同時給指定元素進(jìn)行初始化
- int nums[3]; nums[0] = 1; nums[1] = 2; nums[2] = 3; // 先定義琅摩,后初始化
- 定義但是未初始化,數(shù)組中有值锭硼,但是是垃圾值房资。
- 對于數(shù)組來說,一旦有元素被初始 化,其他元素都被賦值0。
-
計算數(shù)組中元素的個數(shù)
-
int count = sizeof(數(shù)組) / sizeof(數(shù)組[0]) // 數(shù)組的長度 = 數(shù)組占用的總字節(jié)數(shù) / 數(shù)組元素占用的字節(jié)數(shù)
?
-
-
數(shù)組注意事項
-
在定義數(shù)組的時候[]里面只能寫整型常量或者是返回整型常量的表達(dá)式檀头。
int ages['A'] = {19, 22, 33};
printf("ages[0] = %d\n", ages[0]);
int ages[5 + 5] = {19, 22, 33};
printf("ages[0] = %d\n", ages[0]);
int ages['A' + 5] = {19, 22, 33};
printf("ages[0] = %d\n", ages[0])
-
錯誤寫法轰异。
-
沒有指定元素個數(shù)(int nums[] = {1,2,3,5,6}; 這樣是可以的,但是如果先聲明暑始,并沒有初始化搭独,則是錯誤的)
int a[]; // 錯誤
-
[]中不能放變量
int number = 10;
int ages[number]; // 不報錯, 但是沒有初始化, 里面是隨機值
-
-
-
> int number = 10;
>
> int ages[number] = {19, 22, 33} // 直接報錯
- > int ages10[5];
>
> ages10 = {19, 22, 33}; // 錯誤。只能在定義數(shù)組的時候進(jìn)行一次性(全部賦值)的初始化
- 訪問數(shù)組越界廊镜。