易被遺忘的C/C++要點總結

rh_Jameson發表於2016-04-10

一、 資料型別及運算

求補碼

  • 原碼的基礎上, 符號位不變, 其餘各位取反, 最後+1
  • 原碼轉補碼不考慮符號位
  • 補碼轉原碼,符號位不參與運算
  • 取反後 + 1 == 取反前 – 1

科學計數法表示

  • 1.8 * 10^11 –> 1.8E11
  • 9.34 * 10^-3 –> 9.34E-3

相關細節

  • sizeof()是一個運算,而非函式
  • ++運算不能用在實數上
  • 判斷一個整數是否是2^n(2,4,6,8,16…)
    • !(x & (x – 1))
  • 三目條件運算子程式碼更優
    • 編譯器能產生比if…else…更優的程式碼

運算子優先順序、結合方向規則

  • 單目 > 雙目
  • 算術 > 關係 > 位 > 邏輯 > 條件(三目)> 賦值 > 逗號
    • 算術: + – * /
    • 關係: > < >= <=
    • 位: & | ^
    • 單目: ~
    • 邏輯: && ||
    • 單目: !
  • 自右向左的三種運算子
    • 單目
    • 賦值
    • 條件

資料輸入與輸出

  • printf()語句從右向左計算輸出表示式的值
      i = 1;
      printf("%d, %d\\\\n", i++, i--);
      //res: 0,1
      //先執行i--,再執行i++

常用輸出函式

  • printf()
  • putchar()
    • 輸出一個字元
    • 必須是字元型變數或常量
  • puts()
    • 輸出一個字串
    • 必須是字串或常量

常用輸入函式

  • scanf()
  • gets()
    • 每次讀取一個字串
  • getche()
    • conio.h中
    • 讀取字元不用按回車
  • getchar()
    • stdio.h中
    • 完成後須按回車
  • getche() & getchar():
    每次讀取一個字元
  • scanf() & gets()區別:
    scanf不能輸入含空格字串,gets可以

檢視大圖

二、選擇語句和迴圈語句

switch:case 常量表示式

  • 常量表示式只能為整型、字元型
  • 不允許浮點型

三、陣列

定義

  • 定義陣列未賦初值
    • Turbo C會給陣列置0
    • VC則取隨機值
  • 定義靜態陣列,則系統自動賦0

比較字串陣列中的值

  • C:     strcmp(str1,str2)
  • C++:    str1 == str2
  • JAVA:   str1.equals(str2)
    • java中,str1 == str2 比較的是地址

四、指標

指標運算

  • 指標相減:   表示兩指標所指地址之間的資料個數
  • 指標相加:   沒有意義,錯誤

陣列與指標

1、一維陣列首地址

int a[10], *p;
p = &a[0];
p = a
//等價,將陣列首元素的首地址賦給指標p
  • 表示:&a[0], a:  陣列首元素的首地址
    &a:      陣列首地址
  • 對比:
    a == &a[0]
    a != &a    //地址值相同,含義不同

2、二維陣列首地址

int a[10][10];

地址值相同,含義不同:

a:

  • 二維陣列首元素首地址
  • 代表一維陣列元素的首地址

&a:

  • 陣列首地址

&a[0]:

  • 二維陣列首元素首地址

&a[0][0]:

  • &a[0][0] != a
  • a[0] == &a[0][0]

3、二維陣列指標

  • int (*p)[3]:
    • 指向含3個元素的二維陣列的行指標
    • 陣列每列有3個元素
  • int \p[3] & int \(p[3]):
    • 指標陣列,每個元素均是一個指標

指標與引用的區別

  • 非空區別
    • 引用必須總是指向某些物件
      • 不能使用指向空值的引用
      • 不存在指向空值的引用
      • 效率比使用指標高
    • 指標可以指向空值
  • 合法性區別
    • 使用引用前,無需測試其合法性
    • 使用指標總是需要判空
  • 可修改區別
    • 指標可被重新賦值,以指向另一物件
    • 引用
      • 總指向初始化時被指定的物件
      • 以後都不能改變
      • 但指定物件的內容可以改變
  • 應用區別
    • 指標場景
      • 存在不指向任何物件的情況
      • 不同的時刻指向不同物件的情況
    • 引用場景
      • 指向一個物件後就不會改變指向的情況

ps:宣告引用 / const常量 的同時,必須初始化

函式指標

  • float(**def)[10];
    • 二級指標
    • 指向一個一維陣列的指標
    • 陣列元素都是float
  • double\(\gh)[10];
    • 指標gh,指向一個一維陣列
    • 該陣列元素的型別均為double *
  • double(*f[10])();
    • f是一個陣列,含10個元素
      • 元素都是函式指標
    • 指向的函式
      • 沒有引數
      • 返回double型別的值
  • int \( (\b)[10] );
    • 和int \(\b)[10]一樣
  • Long (* fun)(int)
    • 函式指標

五、型別轉換

(int &)相關

  • float a = 1.0f;
  • (int)a實際上是以浮點數a為引數構造了一個整型數,該整數的值是1。
  • (int&)a則是告訴編譯器將a當作整數看(並沒有做任何實質上的轉換)。

unsigned int

  • unsigned int a = 0xFFFFFFF7;
  • unsigned char i = (unsigned char)a;
    • i: 000000f7
  • char \b = (char )&a;
    • *b: fffffff7

隱式型別轉換

  • 算術運算式中,低型別能夠轉換為高型別
  • 賦值運算式
    • 右邊表示式的值自動隱式轉換為左邊變數的型別,並賦值給他
  • 函式呼叫中引數傳遞時,系統隱式地將實參轉換為形參的型別後,賦給形參
  • 函式有返回值時,系統將隱式地將返回表示式型別轉換為返回值型別,賦值給呼叫函式

六、位運算相關

取兩數的平均值:

(x & y) + [(x ^ y) >> 1]

另類取兩數較大值:

max = [(a + b) + abs(a - b)] / 2

三數取中間數:

t1 = max(a, b);
t2 = max(b, c);
t3 = max(a, c);
min( t1, min(t2, t3) )

七、函式

靜態函式:   不可被其他檔案呼叫的函式

函式過載:

  • 引數型別不同
  • 引數個數不同
  • 對返回型別沒有要求

八、#define & const & sizeof

#define例項

* #define SEC (60 * 60 * 24 * 365)UL
* #define MIIN(A, B)    ( (A) <= (B) ? (A) : (B) )

const,#define的區別

  • const
    • 有資料型別
    • 可進行型別安全檢查
    • 可對其進行除錯
  • \#define
    • 沒有資料型別
    • 僅進行字元替換,沒有型別安全檢查
    • 無法除錯
  • c中const
    • 被當做一個不能被改變的普通變數
  • error
    const bufsize = 100;
    char buf[bufsize];

位元組對齊

  • 資料對齊規則
    • 結構的首地址必須是結構內最寬型別的整數倍地址
    • 結構體的每一個成員起始地址必須是自身型別大小的整數倍
  • 結構體的整體大小必須可被對齊值整除
  • 結構體的整體大小必須可被本結構內的最寬型別整除

sizeof

  • 結構體或類內的靜態變數
    struct s{
      int a;
      static int b;
    };
    s ss;
    sizeof(ss)

    結果:4

  • 靜態變數存放在全域性資料區
  • sizeof計算棧中分配的大小
  • 任何型別指標大小相同:4(32位)
  • 對函式使用sizeof
  • 在編譯階段會被函式返回值的型別取代
  • 空類大小
    • 單繼承:1
    • 多繼承:1
    • 虛繼承:4
    • 涉及虛表(虛指標)

行內函數 vs. 巨集

  • 內聯
    • 相比普通函式: 加快程式執行速度
    • 直接嵌入目的碼
    • 要做引數型別檢查
  • 巨集
    • 簡單的替換
    • 不做引數型別檢查

九、 C++物件導向

1、類和物件

類物件的儲存空間

  • 只為每個物件的資料成員和函式地址分配記憶體空間
  • 類中所有成員函式只生成一個副本
  • 該類每個物件執行相同的函式成員

拷貝建構函式

  • 功能
    • 用一個已知的物件來初始化一個被建立的同類的物件
  • 特點
    • 函式只有一個引數,並且是對某個物件的引用
    • 每個類都必須有一個拷貝初始化建構函式
  • 格式
    • 類名::拷貝初始化建構函式名(const 類名 &引用名)

靜態成員

  • 靜態資料成員
    • 特點
      • 類的所有物件共享
      • 必須初始化,且要在類外初始化
    • 引用格式
      • 類名::靜態資料成員名
  • 靜態成員函式
    • 特點
      • 類的所有物件共享
      • 只能使用類的靜態成員和非資料成員
    • 引用格式
      • 類名::靜態成員函式名

類成員指標

const成員函式

定義: 任何不修改成員資料的函式都應宣告為const函式

原型: int GetY() const;

細節:

  • const函式想修改成員變數
    • 在相應變數定義處加上mutable
    • mutable int m_Count;

2、友元函式

定義

  • 需在類體內宣告
  • 可訪問類的私有成員
  • 不是類的成員函式

優點:    提高程式執行效率

缺點:   破壞類的封裝性和隱藏性

特點:    可以是多個類的友元

3、繼承和派生

公有繼承

  • 派生類成員函式可訪問基類中的公有成員和保護成員
  • 派生類的物件僅可訪問基類中的公有成員

派生類

  • 建構函式執行順序
    • 基類建構函式
    • 子物件類的建構函式(如果有的話)
    • 派生類建構函式
  • 解構函式執行順序
    • 派生類的解構函式
    • 基類的解構函式

虛基類

相關文章