天天看點

coursera---C++程式設計重點筆記--week2

課程位址: https://www.coursera.org/learn/cpp-chengxu-sheji

文章目錄

    • 1.1 函數指針
      • 基本概念
      • 從qsort庫函數看函數指針的作用
      • 練習題
    • 1.2 指令行參數
      • 練習
    • 2.1 位運算
    • 2.2 引用
      • 練習
    • 3.1 const關鍵字
      • const定義常量
      • const定義指針
    • 3.2 動态記憶體配置設定
      • 練習
    • 3.3 内聯函數,函數重載,參數預設
      • 函數重載
      • 參數預設
    • 4.1 面向對象的設計方法

1.1 函數指針

基本概念

程式在運作期間,每一個函數都會占用一片連續的記憶體空間。每一個函數都會有一個起始位址。 那在C語言和C++語言裡面,我們可以把一個函數的起始位址指派給一個指針, 那這樣的一個指針就稱為函數指針。

  • 函數指針定義

    類型名 (* 指針變量名)(參數類型1,參數類型2)

    例:

    int (*pf)(int char)

    note:* 指針變量名一定要加括号
  • 函數指針使用

    可以用一個原型比對的函數名字為一個函數指針指派。

    通過函數指針調用指向函數:

    函數指針名(實參表)

    note:原型比對值傳回值類型,參數類型和個數都要相同

從qsort庫函數看函數指針的作用

  • qsort函數聲明

    qsort函數是能對任意類型的數組進行排序的c庫函數

void qsort(void *base, int nelem, unsigned int width,
		 int (* pfCompare)(const void *,const void *));
/*****/
base: 數組的首元素位址
nelem:數組元素的個數
width:每個元素的大小(位元組)
pfCompare: 排序規則
           
  • 排序規則編寫

    格式:

    int 比較函數名(const void * elem1,const void * elem2);

    如果認為elem1應該排在elem2的前面,函數的傳回值就應該是一個負的整數。

    如果認為elem1和elem2哪個排在前面都行,那麼比較函數的傳回值就應該是0。

    如果認為elem1應該排在elem2的後面, 比較函數的傳回值就應該是一個正整數。

    簡而言之:

    不交換傳回負數,交換傳回正數,随意傳回0

#include <stdio.h>
#include <stdlib.h>
//讓數組元素按照個位數大小排序,(從小到大)
int MyCompare(const void * elem1,const void *elem2)
{
	unsigned int *p1,*p2;
	p1 = (unsigned int *)elem1;
	p2 = (unsigned int *)elem2;
	return (*p1 % 10)-(*p2 % 10);
}
int main()
{
	unsigned int an[5] = {12,34,4,51,3};
	qsort(an,5,sizeof(unsigned int),MyCompare);
	for(int i=0;i<5;i++)
		printf("%d ", an[i]);
}
//運作結果
51 12 3 4 34
           

總結:函數指針作為參數,可以傳遞更多的資訊。

練習題

答案 B

coursera---C++程式設計重點筆記--week2

答案:C

coursera---C++程式設計重點筆記--week2

1.2 指令行參數

我們在指令行執行程式的時候是可以帶參數的,那麼我們的程式怎麼接收參數呢?

  • 傳參數

    直接在可執行程式後面輸入參數就行,兩個參數之間用空格隔開

    例:a.exe程式輸入help和in、out三個參數

    a.exe help in out

    note:如果要輸入帶有空格的參數,則需要加雙引号

    a.exe "hello world"

  • 接受參數

    int main(int argc, char * argv[])

    argc: 代表程式啟動的時,指令行參數的個數。c/c++規定,可執行程式本身也是一個參數。是以,argc的值至少是1。

    argv: 指針數組,其中的每一個元素都指向一個參數(字元串)。

#include <stdio.h>
int main(int argc, char * argv[])
{
	printf("the numbers of param: %d \n",argc);
	for(int i=0; i<argc; i++)
		printf(" %s ",argv[i]);
}
           

執行:

a.exe help in out

輸出:

the numbers of param: 4

   

a.exe help in out

note: 在程式啟動的時候,作業系統就已經把使用者在指令行敲進去的參數,存在了某個地方了。作業系統在調用程式的時候再把指令行參數傳進去。

練習

答案:A

coursera---C++程式設計重點筆記--week2

2.1 位運算

嵌入式裡面需要對寄存器進行操作時,用的比較多

c/c++提供了六種位運算符

TYPE 描述
& 按位與(雙目)
| 按位或(雙目)
^ 按位異或(雙目)
~ 按位非(單目)
<< 左移(雙目)
>> 右移(雙目)
  • 按位與&

    功能:

    1.将變量中的某一位清0,同時其他位保持不變;

    2.擷取變量中的某一位;

    例:将int型變量n的低八位全部清零,其他位不變:

    n = n & 0xffffff00;

    例:判斷int型變量的第3位(從右往左,從0開始數)是否為1?

    if (n & 0x08 == 0x08)

    因為0與任何數與都是0,1與任何數與都是任何數。是以我們要将特定數取出就用1去與就行。

    當然如果要将具體位取出還要依賴于移位操作

  • 按位或 |

    功能:

    用來将變量中的某些位置1

  • 按位異或 ^

    兩位相異,結果為1

    兩位相同,結果為0

    1 ^ (任何數) =》 取反

    0 ^ (任何數) =》 不變

    功能:

    1.可以将變量中的某些位取反,而保留其他位不變

    2.可以實作最簡單的加密和解密

    特點:

    如果 a^b=c,則 c^b=a 及 a^c=b

    , 用此特點可以實作最簡單的加密和解密

    例:a是要加密的資料,b是密鑰。c是加密後的資料。

    3.不通過臨時變量,交換兩個變量的值

    這是利用了功能2,以及任何數異或自己等于0,0異或任何數不變,

int a=5,b=8;
	a = a^b;
	b = a^b;
	a = a^b;
	printf("%d, %d \n",a,b);
           
  • 左移運算符 <<

    左移1位,就是乘以2,左移n位,就是乘以2^n

  • 右移運算符 >>

    note: 對于有符号的數,右移時候,符号位也會跟着一起移動。在大多數C和C++編譯器中處理右移:如果原來的那個符号位為1,那右移的時候左邊補充進來的那個高位就都是1, 如果被右移的數符号位是0, 那右移的時候,左邊補充出來的那些位就都是0. 大多數編譯器都是這麼規定的。

    右移1位,就是除以2,右移n位,就是除以2^n。

    并且最後結果是往小裡取整(規律,不是規定)

    -25 >> 4 = -2

2.2 引用

類型名 & 引用名 = 某變量名

某個變量的引用,等價與這個變量,相當于這個變量的别名。

note:

1.定義引用時一定要将其初始化成引用某個變量

2.初始化之後,它就一直引用該變量,不會再引用别的變量了。

3.引用隻能引用變量,不能引用常量和表達式

  • 引用作為函數傳回值
int n=4;
int & SetValue() {return n;}
int main()
{
	SetValue() = 40;
	cout << n;
}
           
  • 常引用

    不能通過常引用去修改其引用的内容

int n=100;
const int &i=n;
r = 200; //編譯出錯
n = 200; //編譯正确
           
  • 常引用和非常引用的轉換

    設T是變量類型,

    const T & 和 T & 是不同的類型 !!!

    T & 類型的引用或T類型的變量可以用來初始化const T&類型的引用。

    const T類型的常變量和const T&類型的引用則不能用來初始化T &類型的引用,除非進行強制類型轉換

練習

答案 C

coursera---C++程式設計重點筆記--week2

3.1 const關鍵字

const定義常量

const double pi = 3.1415926;

double const pi = 3.1415926;

這兩種定義方式都是一樣的含義

在c++裡面盡量用const替代#define,const有類型檢查。

const定義指針

  • 指針本身是不可改變的

    char a = 'a'; char *const pContent = &a;

    指針本身不可以改變

    char b = 'b';pContent = &b;

    但是指向的内容是可以改變的

    *pContent = 'b';

  • 指向的内容不可改變 (常量指針)

    const char * pContent; pContent = &a;

    指向的内容不可通過指針改變

    *pContent = 'b';

    但是可以通過變量自身改變

    a = 'b';

    note:不能把常量指針指派給非常量指針 (可以強制類型轉換)

  • const char * const pContent

3.2 動态記憶體配置設定

按需配置設定記憶體

new的兩種用法

note:用new定義出來的數組編譯時候不會有越界警告

用delete釋放new出來的數組的時候加[]

char *p = new char[10];
delete[] p;
           

練習

答案B

coursera---C++程式設計重點筆記--week2

答案C

coursera---C++程式設計重點筆記--week2

3.3 内聯函數,函數重載,參數預設

一般子函數在編譯的時候都隻會将調用指令編譯進去,随之而來的就是參數入棧,壓棧,彈棧等工作。inline關鍵字的作用就是将整個子函數的内容都編譯進去。

inline在傳回值類型前面

函數重載

一個函數,函數名字相同,參數類型和參數個數不一樣就行

note:不能按照傳回值類型區分函數重載,

因為就算有傳回值的函數在調用的時候也可以不接收傳回值

答案D

coursera---C++程式設計重點筆記--week2

參數預設

c++中,在定義函數的時候,可以讓最右邊的連續多個參數有預設值。那麼在調用函數的時候,若相應的位置不寫參數,則對應的參數就是預設值。

函數參數可預設的目的在于提高程式的可擴充性。

如:在增加某項功能的時候,需要給函數新增參數,那麼原來調用這個函數的代碼也要增加參數,這樣就就會帶來不相容。有了函數預設就能将這兩種需求結合起來。

答案C

coursera---C++程式設計重點筆記--week2

4.1 面向對象的設計方法

結構化程式設計的四大問題:

  • 了解難
  • 修改難
  • 查錯難
  • 重用難

繼續閱讀