10-C語言進(jìn)制和位運(yùn)算-指趣學(xué)院

進(jìn)制基本概念

  • 什么是進(jìn)制?

    • 進(jìn)制是一種計(jì)數(shù)的方式,數(shù)值的表示形式
  • 常見的進(jìn)制

    • 十進(jìn)制遥昧、二進(jìn)制覆醇、八進(jìn)制、十六進(jìn)制
  • 進(jìn)制書寫的格式和規(guī)律

    • 十進(jìn)制 0炭臭、1永脓、2、3鞋仍、4憨奸、5、6凿试、7排宰、8、9 逢十進(jìn)一
    • 二進(jìn)制 0那婉、1 逢二進(jìn)一
      • 書寫形式:需要以0b或者0B開頭,例如: 0b101
    • 八進(jìn)制 0板甘、1、2详炬、3盐类、4寞奸、5、6在跳、7 逢八進(jìn)一
      • 書寫形式:在前面加個(gè)0,例如: 061
    • 十六進(jìn)制 0枪萄、1、2猫妙、3瓷翻、4、5割坠、6齐帚、7、8彼哼、9对妄、A、B敢朱、C剪菱、D、E拴签、F 逢十六進(jìn)一
    • 書寫形式:在前面加個(gè)0x或者0X,例如: 0x45
  • 練習(xí)

    • 1.用不同進(jìn)制表示如下有多少個(gè)方格
    • 2.判斷下列數(shù)字是否合理
    00011  0x001  0x7h4  10.98  0986  .089-109
    +178  0b325  0b0010  0xffdc 96f 96.0f 96.oF  -.003
    

進(jìn)制轉(zhuǎn)換

  • 10 進(jìn)制轉(zhuǎn) 2 進(jìn)制
    • 除2取余, 余數(shù)倒序; 得到的序列就是二進(jìn)制表示形式
    • 例如: 將十進(jìn)制(97) 10轉(zhuǎn)換為二進(jìn)制數(shù)

  • 2 進(jìn)制轉(zhuǎn) 10 進(jìn)制
    • 每一位二進(jìn)制進(jìn)制位的值 * 2的當(dāng)前索引次冪; 再將所有位求出的值相加
    • 例如: 將二進(jìn)制01100100轉(zhuǎn)換為十進(jìn)制
    01100100
    索引從右至左, 從零開始
    第0位: 0 * 2^0 = 0;
    第1位: 0 * 2^1 = 0;
    第2位: 1 * 2^2 = 4;
    第3位: 0 * 2^3 = 0;
    第4位: 0 * 2^4 = 0;
    第5位: 1 * 2^5 = 32;
    第6位: 1 * 2^6 = 64;
    第7位: 0 * 2^7 = 0;
    最終結(jié)果為: 0 + 0 + 4 + 0 + 0 + 32 + 64 + 0 = 100
    

  • 2 進(jìn)制轉(zhuǎn) 8 進(jìn)制
    • 三個(gè)二進(jìn)制位代表一個(gè)八進(jìn)制位, 因?yàn)?個(gè)二進(jìn)制位的最大值是7孝常,而八進(jìn)制是逢8進(jìn)1
    • 例如: 將二進(jìn)制01100100轉(zhuǎn)換為八進(jìn)制數(shù)
    從右至左每3位劃分為8進(jìn)制的1位, 不夠前面補(bǔ)0
    001 100 100
    第0位: 100 等于十進(jìn)制 4
    第1位: 100 等于十進(jìn)制 4
    第2位: 001 等于十進(jìn)制 1
    最終結(jié)果: 144就是轉(zhuǎn)換為8進(jìn)制的值
    

  • 2 進(jìn)制轉(zhuǎn) 16 進(jìn)制
    • 四個(gè)二進(jìn)制位代表一個(gè)十六進(jìn)制位,因?yàn)?個(gè)二進(jìn)制位的最大值是15篓吁,而十六進(jìn)制是逢16進(jìn)1
    • 例如: 將二進(jìn)制01100100轉(zhuǎn)換為十六進(jìn)制數(shù)
    從右至左每4位劃分為16進(jìn)制的1位, 不夠前面補(bǔ)0
    0110 0100
    第0位: 0100 等于十進(jìn)制 4
    第1位: 0110 等于十進(jìn)制 6
    最終結(jié)果: 64就是轉(zhuǎn)換為16進(jìn)制的值
    

  • 其它進(jìn)制轉(zhuǎn)換為十進(jìn)制
    • 系數(shù) * 基數(shù) ^ 索引 之和
        十進(jìn)制           -->          十進(jìn)制
       12345   =  10000 + 2000 + 300 + 40 + 5
               =  (1 * 10 ^ 4)  + (2 * 10 ^ 3) + (3 * 10 ^ 2) + (4 * 10 ^ 1) + (5 * 10 ^ 0)
               =  (1 * 10000) + (2 + 1000) + (3 * 100) + (4 * 10) + (5 * 1)
               =  10000 + 2000 + 300 + 40 + 5
               =  12345
       
       規(guī)律:
       其它進(jìn)制轉(zhuǎn)換為十進(jìn)制的結(jié)果 = 系數(shù) * 基數(shù) ^ 索引 之和
       
       系數(shù): 每一位的值就是一個(gè)系數(shù) 
       基數(shù): 從x進(jìn)制轉(zhuǎn)換到十進(jìn)制, 那么x就是基數(shù)
       索引: 從最低位以0開始, 遞增的數(shù)
    
       二進(jìn)制        -->      十進(jìn)制
       543210
       101101 = (1 * 2 ^ 5) + (0 * 2 ^ 4) + (1 * 2 ^ 3) + (1 * 2 ^ 2) + (0 * 2 ^ 1) + (1 * 2 ^ 0)
              = 32 + 0 + 8 + 4 + 0 + 1
              = 45
       
       八進(jìn)制        -->     十進(jìn)制
       016  =   (0 * 8 ^ 2) + (1 * 8 ^ 1) + (6 * 8 ^ 0)
            =    0  + 8 + 6
            =    14
       
       十六進(jìn)制      -->      十進(jìn)制
       0x11f =  (1 * 16 ^ 2) + (1 * 16 ^ 1) + (15 * 16 ^ 0)
             =   256  + 16 + 15
             =   287
    

  • 十進(jìn)制快速轉(zhuǎn)換為其它進(jìn)制
    • 十進(jìn)制除以基數(shù)取余, 倒敘讀取
       十進(jìn)制        -->     二進(jìn)制
       100          -->    1100100
       100 / 2   = 50     0
       50  / 2   = 25     0
       25  / 2   = 12     1
       12  / 2   = 6      0
       6   / 2   = 3      0
       3   / 2   = 1      1
       1   / 2   = 0      1
       
       
       十進(jìn)制        -->     八進(jìn)制
       100          -->     144
       100 / 8    = 12    4
       12  / 8    = 1     4
       1   / 8    = 0     1
       
       十進(jìn)制        -->     十六進(jìn)制
       100          --> 64
       100 / 16   =  6    4
       6   / 16   =  0    6
    

十進(jìn)制小數(shù)轉(zhuǎn)換為二進(jìn)制小數(shù)

  • 整數(shù)部分,直接轉(zhuǎn)換為二進(jìn)制即可
  • 小數(shù)部分,使用"乘2取整茫因,順序排列"
    • 用2乘十進(jìn)制小數(shù),可以得到積,將積的整數(shù)部分取出,再用2乘余下的小數(shù)部分,直到積中的小數(shù)部分為零蚪拦,或者達(dá)到所要求的精度為止
    • 然后把取出的整數(shù)部分按順序排列起來, 即是小數(shù)部分二進(jìn)制
  • 最后將整數(shù)部分的二進(jìn)制和小數(shù)部分的二進(jìn)制合并起來, 即是一個(gè)二進(jìn)制小數(shù)
  • 例如: 將12.125轉(zhuǎn)換為二進(jìn)制
// 整數(shù)部分(除2取余)
  12
/  2
------
   6    // 余0
/  2
------
   3    // 余0
/  2
------
   1   // 余1
/  2
------
  0   // 余1
//12 --> 1100
  
// 小數(shù)部分(乘2取整數(shù)積)
  0.125
*     2
  ------
   0.25  //0
   0.25
*     2
  ------
    0.5  //0
    0.5
*     2
  ------
    1.0  //1
    0.0
// 0.125 --> 0.001

// 12.8125 --> 1100.001

二進(jìn)制小數(shù)轉(zhuǎn)換為十進(jìn)制小數(shù)

  • 整數(shù)部分按照二進(jìn)制轉(zhuǎn)十進(jìn)制即可
  • 小數(shù)部分從最高位開始乘以2的負(fù)n次方, n從1開始
  • 例如: 將 1100.001轉(zhuǎn)換為十進(jìn)制
// 整數(shù)部分(乘以2的n次方, n從0開始)
0 * 2^0 = 0
0 * 2^1 = 0
1 * 2^2 = 4
1 * 2^3 = 8
 // 1100 == 8 + 4 + 0 + 0 == 12

// 小數(shù)部分(乘以2的負(fù)n次方, n從0開始)
0 * (1/2) = 0
0 * (1/4) = 0
1 * (1/8) = 0.125
// .100 == 0 + 0 + 0.125 == 0.125

// 1100.001  --> 12.125
  • 練習(xí):
    • 將0.8125轉(zhuǎn)換為二進(jìn)制
    • 將0.1101轉(zhuǎn)換為十進(jìn)制
  0.8125
*      2
--------
   1.625  // 1
   0.625
*      2
--------
    1.25 // 1
    0.25
*      2
--------
     0.5 // 0
*      2
--------
    1.0 // 1
    0.0

// 0. 8125  --> 0.1101
1*(1/2) = 0.5
1*(1/4)=0.25
0*(1/8)=0
1*(1/16)=0.0625

//0.1101 --> 0.5 + 0.25 + 0 + 0.0625 == 0.8125

原碼反碼補(bǔ)碼

  • 計(jì)算機(jī)只能識(shí)別0和1, 所以計(jì)算機(jī)中存儲(chǔ)的數(shù)據(jù)都是以0和1的形式存儲(chǔ)的
  • 數(shù)據(jù)在計(jì)算機(jī)內(nèi)部是以補(bǔ)碼的形式儲(chǔ)存的, 所有數(shù)據(jù)的運(yùn)算都是以補(bǔ)碼進(jìn)行的
  • 正數(shù)的原碼杖剪、反碼和補(bǔ)碼
    • 正數(shù)的原碼、反碼和補(bǔ)碼都是它的二進(jìn)制
    • 例如: 12的原碼驰贷、反碼和補(bǔ)碼分別為
      • 0000 0000 0000 0000 0000 0000 0000 1100
      • 0000 0000 0000 0000 0000 0000 0000 1100
      • 0000 0000 0000 0000 0000 0000 0000 1100
  • 負(fù)數(shù)的原碼盛嘿、反碼和補(bǔ)碼
    • 二進(jìn)制的最高位我們稱之為符號(hào)位, 最高位是0代表是一個(gè)正數(shù), 最高位是1代表是一個(gè)負(fù)數(shù)
    • 一個(gè)負(fù)數(shù)的原碼, 是將該負(fù)數(shù)的二進(jìn)制最高位變?yōu)?
    • 一個(gè)負(fù)數(shù)的反碼, 是將該數(shù)的原碼除了符號(hào)位以外的其它位取反
    • 一個(gè)負(fù)數(shù)的補(bǔ)碼, 就是它的反碼 + 1
    • 例如: -12的原碼、反碼和補(bǔ)碼分別為
      0000 0000 0000 0000 0000 0000 0000 1100 // 12二進(jìn)制
      1000 0000 0000 0000 0000 0000 0000 1100 // -12原碼
      1111 1111 1111 1111 1111 1111 1111 0011  // -12反碼
      1111 1111 1111 1111 1111 1111 1111 0100 // -12補(bǔ)碼
    
  • 負(fù)數(shù)的原碼括袒、反碼和補(bǔ)碼逆向轉(zhuǎn)換
    • 反碼 = 補(bǔ)碼-1
    • 原碼= 反碼最高位不變, 其它位取反
      1111 1111 1111 1111 1111 1111 1111 0100 // -12補(bǔ)碼
      1111 1111 1111 1111 1111 1111 1111 0011  // -12反碼
      1000 0000 0000 0000 0000 0000 0000 1100 // -12原碼
    

  • 為什么要引入反碼和補(bǔ)碼
    • 在學(xué)習(xí)本節(jié)內(nèi)容之前,大家必須明白一個(gè)東西, 就是計(jì)算機(jī)只能做加法運(yùn)算, 不能做減法和乘除法, 所以的減法和乘除法內(nèi)部都是用加法來實(shí)現(xiàn)的
      • 例如: 1 - 1, 內(nèi)部其實(shí)就是 1 + (-1);
      • 例如: 3 * 3, 內(nèi)部其實(shí)就是 3 + 3 + 3;
      • 例如: 9 / 3, 內(nèi)部其實(shí)就是 9 + (-3) + (-3) + (-3);
    • 首先我們先來觀察一下,如果只有原碼會(huì)存儲(chǔ)什么問題
      • 很明顯, 通過我們的觀察, 如果只有原碼, 1-1的結(jié)果不對(duì)
        // 1 + 1
         0000 0000 0000 0000 0000 0000 0000 0001 // 1原碼
        +0000 0000 0000 0000 0000 0000 0000 0001 // 1原碼
         ---------------------------------------
         0000 0000 0000 0000 0000 0000 0000 0010  == 2
      
         // 1 - 1; 1 + (-1);
         0000 0000 0000 0000 0000 0000 0000 0001 // 1原碼
        +1000 0000 0000 0000 0000 0000 0000 0001 // -1原碼
         ---------------------------------------
         1000 0000 0000 0000 0000 0000 0000 0010 == -2
      
    • 正是因?yàn)閷?duì)于減法來說,如果使用原碼結(jié)果是不正確的, 所以才引入了反碼
      • 通過反碼計(jì)算減法的結(jié)果, 得到的也是一個(gè)反碼;
      • 將計(jì)算的結(jié)果符號(hào)位不變其余位取反,就得到了計(jì)算結(jié)果的原碼
      • 通過對(duì)原碼的轉(zhuǎn)換, 很明顯我們計(jì)算的結(jié)果是-0, 符合我們的預(yù)期
      // 1 - 1; 1 + (-1);
      0000 0000 0000 0000 0000 0000 0000 0001 // 1反碼
      1111 1111 1111 1111 1111 1111 1111 1110   // -1反碼
      ---------------------------------------
      1111 1111 1111 1111 1111 1111 1111 1111 // 計(jì)算結(jié)果反碼
      1000 0000 0000 0000 0000 0000 0000 0000 // 計(jì)算結(jié)果原碼 == -0
    
    • 雖然反碼能夠滿足我們的需求, 但是對(duì)于0來說, 前面的負(fù)號(hào)沒有任何意義, 所以才引入了補(bǔ)碼
      • 由于int只能存儲(chǔ)4個(gè)字節(jié), 也就是32位數(shù)據(jù), 而計(jì)算的結(jié)果又33位, 所以最高位溢出了,符號(hào)位變成了0, 所以最終得到的結(jié)果是0
      // 1 - 1; 1 + (-1);
      0000 0000 0000 0000 0000 0000 0000 0001 // 1補(bǔ)碼
      1111 1111 1111 1111 1111 1111 1111 1111   // -1補(bǔ)碼
      ---------------------------------------
     10000 0000 0000 0000 0000 0000 0000 0000 // 計(jì)算結(jié)果補(bǔ)碼
      0000 0000 0000 0000 0000 0000 0000 0000 //  == 0
    

位運(yùn)算符

  • 程序中的所有數(shù)據(jù)在計(jì)算機(jī)內(nèi)存中都是以二進(jìn)制的形式儲(chǔ)存的次兆。
  • 位運(yùn)算就是直接對(duì)整數(shù)在內(nèi)存中的二進(jìn)制位進(jìn)行操作
  • C語言提供了6個(gè)位操作運(yùn)算符, 這些運(yùn)算符只能用于整型操作數(shù)
符號(hào) 名稱 運(yùn)算結(jié)果
& 按位與 同1為1
| 按位或 有1為1
^ 按位異或 不同為1
~ 按位取反 0變1,1變0
<< 按位左移 乘以2的n次方
>> 按位右移 除以2的n次方

  • 按位與:
    • 只有對(duì)應(yīng)的兩個(gè)二進(jìn)位均為1時(shí),結(jié)果位才為1锹锰,否則為0
    • 規(guī)律: 二進(jìn)制中芥炭,與1相&就保持原位,與0相&就為0
9&5 = 1

 1001
&0101
------
 0001

  • 按位或:
    • 只要對(duì)應(yīng)的二個(gè)二進(jìn)位有一個(gè)為1時(shí)恃慧,結(jié)果位就為1园蝠,否則為0
9|5 = 13

 1001
|0101
------
 1101

  • 按位異或
    • 當(dāng)對(duì)應(yīng)的二進(jìn)位相異(不相同)時(shí),結(jié)果為1痢士,否則為0
    • 規(guī)律:
      • 相同整數(shù)相的結(jié)果是0彪薛。比如55=0
      • 多個(gè)整數(shù)相^的結(jié)果跟順序無關(guān)。例如: 567=576
      • 同一個(gè)數(shù)異或另外一個(gè)數(shù)兩次, 結(jié)果還是那個(gè)數(shù)。例如: 577 = 5
9^5 = 12

 1001
^0101
------
 1100

  • 按位取反
    • 各二進(jìn)位進(jìn)行取反(0變1善延,1變0)
~9 =-10
0000 0000 0000 0000 0000 1001 // 取反前
1111 1111 1111 1111 1111 0110 // 取反后

// 根據(jù)負(fù)數(shù)補(bǔ)碼得出結(jié)果
1111 1111 1111 1111 1111 0110 // 補(bǔ)碼
1111 1111 1111 1111 1111 0101 // 反碼
1000 0000 0000 0000 0000 1010 // 源碼 == -10

  • 位運(yùn)算應(yīng)用場(chǎng)景:
    • 判斷奇偶(按位或)
       偶數(shù): 的二進(jìn)制是以0結(jié)尾
       8   -> 1000
       10  -> 1010
       
       奇數(shù): 的二進(jìn)制是以1結(jié)尾
       9   -> 1001
       11  -> 1011
    
       任何數(shù)和1進(jìn)行&操作,得到這個(gè)數(shù)的最低位
       1000
      &0001
       -----
       0000  // 結(jié)果為0, 代表是偶數(shù)
    
       1011
      &0001
       -----
       0001 // 結(jié)果為1, 代表是奇數(shù)
    
    • 權(quán)限系統(tǒng)
      enum Unix {
        S_IRUSR = 256,// 100000000 用戶可讀
        S_IWUSR = 128,//  10000000 用戶可寫
        S_IXUSR = 64,//    1000000 用戶可執(zhí)行
        S_IRGRP = 32,//     100000 組可讀
        S_IWGRP = 16,//      10000 組可寫
        S_IXGRP = 8,//        1000 組可執(zhí)行
        S_IROTH = 4,//         100 其它可讀
        S_IWOTH = 2,//          10 其它可寫
        S_IXOTH = 1 //           1 其它可執(zhí)行
       };
    // 假設(shè)設(shè)置用戶權(quán)限為可讀可寫
    printf("%d\n", S_IRUSR | S_IWUSR); // 384 // 110000000
    
    • 交換兩個(gè)數(shù)的值(按位異或)
     a = a^b;
     b = b^a;
     a = a^b;
    

  • 按位左移
    • 把整數(shù)a的各二進(jìn)位全部左移n位少态,高位丟棄,低位補(bǔ)0
      • 由于左移是丟棄最高位易遣,0補(bǔ)最低位彼妻,所以符號(hào)位也會(huì)被丟棄,左移出來的結(jié)果值可能會(huì)改變正負(fù)性
    • 規(guī)律: 左移n位其實(shí)就是乘以2的n次方
2<<1; //相當(dāng)于 2 *= 2 // 4
  0010
<<0100

2<<2; //相當(dāng)于 2 *= 2^2; // 8
  0010
<<1000
  • 按位右移
    • 把整數(shù)a的各二進(jìn)位全部右移n位训挡,保持符號(hào)位不變
      • 為正數(shù)時(shí)澳骤, 符號(hào)位為0,最高位補(bǔ)0
      • 為負(fù)數(shù)時(shí)澜薄,符號(hào)位為1为肮,最高位是補(bǔ)0或是補(bǔ)1(取決于編譯系統(tǒng)的規(guī)定)
    • 規(guī)律: 快速計(jì)算一個(gè)數(shù)除以2的n次方
2>>1; //相當(dāng)于 2 /= 2 // 1
  0010
>>0001
4>>2; //相當(dāng)于 4 /= 2^2 // 1
  0100
>>0001
  • 練習(xí):
    • 寫一個(gè)函數(shù)把一個(gè)10進(jìn)制數(shù)按照二進(jìn)制格式輸出
#include <stdio.h>
void printBinary(int num);
int main(int argc, const char * argv[]) {
    printBinary(13);
}
void printBinary(int num){
    int len = sizeof(int)*8;
    int temp;
    for (int i=0; i<len; i++) {
        temp = num; //每次都在原數(shù)的基礎(chǔ)上進(jìn)行移位運(yùn)算
        temp = temp>>(31-i); //每次移動(dòng)的位數(shù)
        int t = temp&1; //取出最后一位
        if(i!=0&&i%4==0)printf(" "); printf("%d",t);
    }
}

變量?jī)?nèi)存分析

  • 內(nèi)存模型
    • 內(nèi)存模型是線性的(有序的)
    • 對(duì)于 32 機(jī)而言,最大的內(nèi)存地址是2^32次方bit(4294967296)(4GB)
    • 對(duì)于 64 機(jī)而言肤京,最大的內(nèi)存地址是2^64次方bit(18446744073709552000)(171億GB)
  • CPU 讀寫內(nèi)存
    • CPU 在運(yùn)作時(shí)要明確三件事
      • 存儲(chǔ)單元的地址(地址信息)
      • 器件的選擇颊艳,讀 or 寫 (控制信息)
      • 讀寫的數(shù)據(jù) (數(shù)據(jù)信息)
  • 如何明確這三件事情
    • 通過地址總線找到存儲(chǔ)單元的地址
    • 通過控制總線發(fā)送內(nèi)存讀寫指令
    • 通過數(shù)據(jù)總線傳輸需要讀寫的數(shù)據(jù)
  • 地址總線: 地址總線寬度決定了CPU可以訪問的物理地址空間(尋址能力)
    • 例如: 地址總線的寬度是1位, 那么表示可以訪問 0 和 1的內(nèi)存
    • 例如: 地址總線的位數(shù)是2位, 那么表示可以訪問 00、01忘分、10棋枕、11的內(nèi)存
  • 數(shù)據(jù)總線: 數(shù)據(jù)總線的位數(shù)決定CPU單次通信能交換的信息數(shù)量
    • 例如: 數(shù)據(jù)總線:的寬度是1位, 那么一次可以傳輸1位二進(jìn)制數(shù)據(jù)
    • 例如: 地址總線的位數(shù)是2位,那么一次可以傳輸2位二進(jìn)制數(shù)據(jù)
  • 控制總線: 用來傳送各種控制信號(hào)
  • 寫入流程
    • CPU 通過地址線將找到地址為 FFFFFFFB 的內(nèi)存
    • CPU 通過控制線發(fā)出內(nèi)存寫入命令,選中存儲(chǔ)器芯片妒峦,并通知它重斑,要其寫入數(shù)據(jù)。
    • CPU 通過數(shù)據(jù)線將數(shù)據(jù) 8 送入內(nèi)存 FFFFFFFB 單元中


  • 讀取流程
    • CPU 通過地址線將找到地址為 FFFFFFFB 的內(nèi)存
    • CPU 通過控制線發(fā)出內(nèi)存讀取命令肯骇,選中存儲(chǔ)器芯片窥浪,并通知它,將要從中讀取數(shù)據(jù)
    • 存儲(chǔ)器將 FFFFFFFB 號(hào)單元中的數(shù)據(jù) 8 通過數(shù)據(jù)線送入 CPU寄存器中


  • 變量的存儲(chǔ)原則
    • 先分配字節(jié)地址大內(nèi)存,然后分配字節(jié)地址小的內(nèi)存(內(nèi)存尋址是由大到小)
    • 變量的首地址,是變量所占存儲(chǔ)空間字節(jié)地址(最小的那個(gè)地址 )
    • 低位保存在低地址字節(jié)上,高位保存在高地址字節(jié)上
    10的二進(jìn)制: 0b00000000 00000000 00000000 00001010
               高字節(jié)←                        →低字節(jié)
    

char類型內(nèi)存存儲(chǔ)細(xì)節(jié)

  • char類型基本概念
    • char是C語言中比較靈活的一種數(shù)據(jù)類型笛丙,稱為“字符型”
    • char類型變量占1個(gè)字節(jié)存儲(chǔ)空間漾脂,共8位
    • 除單個(gè)字符以外, C語言的的轉(zhuǎn)義字符也可以利用char類型存儲(chǔ)
字符 意義
\b 退格(BS)當(dāng)前位置向后回退一個(gè)字符
\r 回車(CR),將當(dāng)前位置移至本行開頭
\n 換行(LF),將當(dāng)前位置移至下一行開頭
\t 水平制表(HT),跳到下一個(gè) TAB 位置
\0 用于表示字符串的結(jié)束標(biāo)記
\ 代表一個(gè)反斜線字符 \
\" 代表一個(gè)雙引號(hào)字符"
\' 代表一個(gè)單引號(hào)字符'
  • char型數(shù)據(jù)存儲(chǔ)原理
    • 計(jì)算機(jī)只能識(shí)別0和1, 所以char類型存儲(chǔ)數(shù)據(jù)并不是存儲(chǔ)一個(gè)字符, 而是將字符轉(zhuǎn)換為0和1之后再存儲(chǔ)
    • 正是因?yàn)榇鎯?chǔ)字符類型時(shí)需要將字符轉(zhuǎn)換為0和1, 所以為了統(tǒng)一, 老美就定義了一個(gè)叫做ASCII表的東東
    • ASCII表中定義了每一個(gè)字符對(duì)應(yīng)的整數(shù)


    char ch1 = 'a'; 
    printf("%i\n", ch1); // 97

    char ch2 = 97;
    printf("%c\n", ch2); // a
  • char類型注意點(diǎn)
    • char類型占一個(gè)字節(jié), 一個(gè)中文字符占3字節(jié)(unicode表),所有char不可以存儲(chǔ)中文
    char c = '我'; // 錯(cuò)誤寫法
    
    • 除轉(zhuǎn)義字符以外, 不支持多個(gè)字符
    char ch = 'ab'; // 錯(cuò)誤寫法
    
    • char類型存儲(chǔ)字符時(shí)會(huì)先查找對(duì)應(yīng)的ASCII碼值, 存儲(chǔ)的是ASCII值, 所以字符6和數(shù)字6存儲(chǔ)的內(nèi)容不同
    char ch1 = '6'; // 存儲(chǔ)的是ASCII碼 64
    char ch2 = 6; //  存儲(chǔ)的是數(shù)字 6
    
  • 練習(xí)
    • 定義一個(gè)函數(shù), 實(shí)現(xiàn)輸入一個(gè)小寫字母,要求轉(zhuǎn)換成大寫輸出

類型說明符

  • 類型說明符基本概念
    • C語言提供了說明長(zhǎng)度說明符號(hào)位的兩種類型說明符, 這兩種類型說明符一共有4個(gè):
      • short 短整型 (說明長(zhǎng)度)
      • long 長(zhǎng)整型 (說明長(zhǎng)度)
      • signed 有符號(hào)型 (說明符號(hào)位)
      • unsigned 無符號(hào)型 (說明符號(hào)位)
  • 這些說明符一般都是用來修飾int類型的,所以在使用時(shí)可以省略int
  • 這些說明符都屬于C語言關(guān)鍵字

short和long

  • short和long可以提供不同長(zhǎng)度的整型數(shù)胚鸯,也就是可以改變整型數(shù)的取值范圍骨稿。
    • 在64bit編譯器環(huán)境下,int占用4個(gè)字節(jié)(32bit)姜钳,取值范圍是-2^31 ~ 2^31-1坦冠;
    • short占用2個(gè)字節(jié)(16bit),取值范圍是-2^15 ~ 2^15-1哥桥;
    • long占用8個(gè)字節(jié)(64bit)辙浑,取值范圍是-2^63 ~ 2^63-1
  • 總結(jié)一下:在64位編譯器環(huán)境下:
    • short占2個(gè)字節(jié)(16位)
    • int占4個(gè)字節(jié)(32位)
    • long占8個(gè)字節(jié)(64位)。
    • 因此泰讽,如果使用的整數(shù)不是很大的話例衍,可以使用short代替int昔期,這樣的話,更節(jié)省內(nèi)存開銷佛玄。
  • 世界上的編譯器林林總總硼一,不同編譯器環(huán)境下,int梦抢、short般贼、long的取值范圍和占用的長(zhǎng)度又是不一樣的。比如在16bit編譯器環(huán)境下奥吩,long只占用4個(gè)字節(jié)哼蛆。不過幸運(yùn)的是,ANSI \ ISO制定了以下規(guī)則:
    • short跟int至少為16位(2字節(jié))
    • long至少為32位(4字節(jié))
    • short的長(zhǎng)度不能大于int霞赫,int的長(zhǎng)度不能大于long
    • char一定為為8位(1字節(jié))腮介,畢竟char是我們編程能用的最小數(shù)據(jù)類型
  • 可以連續(xù)使用2個(gè)long,也就是long long端衰。一般來說叠洗,long long的范圍是不小于long的,比如在32bit編譯器環(huán)境下旅东,long long占用8個(gè)字節(jié)灭抑,long占用4個(gè)字節(jié)。不過在64bit編譯器環(huán)境下抵代,long long跟long是一樣的腾节,都占用8個(gè)字節(jié)。
#include <stdio.h>

int main()
{
    // char占1個(gè)字節(jié), char的取值范圍 -2^7~2^7
    char num = 129;
    printf("size = %i\n", sizeof(num)); // 1
    printf("num = %i\n", num); // -127
    // short int 占2個(gè)字節(jié), short int的取值范圍 -2^15~2^15-1
    short int num1 = 32769;// -32767
    printf("size = %i\n", sizeof(num1)); // 2
    printf("num1 = %hi\n", num1);

    // int占4個(gè)字節(jié), int的取值范圍 -2^31~2^31-1
    int num2 = 12345678901;
    printf("size = %i\n", sizeof(num2)); // 4
    printf("num2 = %i\n", num2);

    // long在32位占4個(gè)字節(jié), 在64位占8個(gè)字節(jié)
    long int num3 = 12345678901;
    printf("size = %i\n", sizeof(num3)); // 4或8
    printf("num3 = %ld\n", num3);

    // long在32位占8個(gè)字節(jié), 在64位占8個(gè)字節(jié) -2^63~2^63-1
    long long int num4 = 12345678901;
    printf("size = %i\n", sizeof(num4)); // 8
    printf("num4 = %lld\n", num4);
    
    // 由于short/long/long long一般都是用于修飾int, 所以int可以省略
    short num5 = 123;
    printf("num5 = %lld\n", num5);
    long num6 = 123;
    printf("num6 = %lld\n", num6);
    long long num7 = 123;
    printf("num7 = %lld\n", num7);
    return 0;
}

signed和unsigned

  • 首先要明確的:signed int等價(jià)于signed荤牍,unsigned int等價(jià)于unsigned
  • signed和unsigned的區(qū)別就是它們的最高位是否要當(dāng)做符號(hào)位案腺,并不會(huì)像short和long那樣改變數(shù)據(jù)的長(zhǎng)度,即所占的字節(jié)數(shù)参淫。
    • signed:表示有符號(hào)救湖,也就是說最高位要當(dāng)做符號(hào)位愧杯。但是int的最高位本來就是符號(hào)位涎才,因此signed和int是一樣的,signed等價(jià)于signed int力九,也等價(jià)于int耍铜。signed的取值范圍是-2^31 ~ 2^31 - 1
    • unsigned:表示無符號(hào),也就是說最高位并不當(dāng)做符號(hào)位跌前,所以不包括負(fù)數(shù)棕兼。
    • 因此unsigned的取值范圍是:0000 0000 0000 0000 0000 0000 0000 0000 ~ 1111 1111 1111 1111 1111 1111 1111 1111,也就是0 ~ 2^32 - 1
#include <stdio.h>

int main()
{
    // 1.默認(rèn)情況下所有類型都是由符號(hào)的
    int num1 = 9;
    int num2 = -9;
    int num3 = 0;
    printf("num1 = %i\n", num1);
    printf("num2 = %i\n", num2);
    printf("num3 = %i\n", num3);

    // 2.signed用于明確說明, 當(dāng)前保存的數(shù)據(jù)可以是有符號(hào)的, 一般情況下很少使用
    signed int num4 = 9;
    signed int num5 = -9;
    signed int num6 = 0;
    printf("num4 = %i\n", num4);
    printf("num5 = %i\n", num5);
    printf("num6 = %i\n", num6);

    // signed也可以省略數(shù)據(jù)類型, 但是不推薦這樣編寫
    signed num7 = 9;
    printf("num7 = %i\n", num7);
   

    // 3.unsigned用于明確說明, 當(dāng)前不能保存有符號(hào)的值, 只能保存0和正數(shù)
    // 應(yīng)用場(chǎng)景: 保存銀行存款,學(xué)生分?jǐn)?shù)等不能是負(fù)數(shù)的情況
    unsigned int num8 = -9;
    unsigned int num9 = 0;
    unsigned int num10 = 9;
    // 注意: 不看怎么存只看怎么取
    printf("num8 = %u\n", num8);
    printf("num9 = %u\n", num9);
    printf("num10 = %u\n", num10);
    return 0;
}
  • 注意點(diǎn):
    • 修飾符號(hào)的說明符可以和修飾長(zhǎng)度的說明符混合使用
    • 相同類型的說明符不能混合使用
    signed short int num1 = 666;
    signed unsigned int num2 = 666; // 報(bào)錯(cuò)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末抵乓,一起剝皮案震驚了整個(gè)濱河市伴挚,隨后出現(xiàn)的幾起案子靶衍,更是在濱河造成了極大的恐慌,老刑警劉巖茎芋,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件颅眶,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡田弥,警方通過查閱死者的電腦和手機(jī)涛酗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來偷厦,“玉大人商叹,你說我怎么就攤上這事≈黄茫” “怎么了剖笙?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)请唱。 經(jīng)常有香客問我枯途,道長(zhǎng),這世上最難降的妖魔是什么籍滴? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任酪夷,我火速辦了婚禮,結(jié)果婚禮上孽惰,老公的妹妹穿的比我還像新娘晚岭。我一直安慰自己,他們只是感情好勋功,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布坦报。 她就那樣靜靜地躺著,像睡著了一般狂鞋。 火紅的嫁衣襯著肌膚如雪片择。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天骚揍,我揣著相機(jī)與錄音字管,去河邊找鬼。 笑死信不,一個(gè)胖子當(dāng)著我的面吹牛嘲叔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播抽活,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼硫戈,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了下硕?” 一聲冷哼從身側(cè)響起丁逝,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤汁胆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后霜幼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沦泌,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年辛掠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了谢谦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡萝衩,死狀恐怖回挽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情猩谊,我是刑警寧澤千劈,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站牌捷,受9級(jí)特大地震影響墙牌,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜暗甥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一喜滨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧撤防,春花似錦虽风、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至漾肮,卻和暖如春厂抖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背克懊。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來泰國(guó)打工忱辅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人保檐。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓耕蝉,卻偏偏與公主長(zhǎng)得像崔梗,于是被迫代替她去往敵國(guó)和親夜只。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容