C 知識點複習

2021-06-29 00:07:00 字數 4097 閱讀 9307

static

static變數只能初始化一次:

#include #include using namespace std;

void fun(int i)

int main()

輸出為:

0

00

因為static變數只初始化一次,static int value = i這句話只執行一次,也就是fun(0)的時候執行。之後這條語句就不再執行。所以value一直為0。

#include #include using namespace std;

void fun(int i)

int main()

輸出:

1

23

const

const修飾指標:

const char * p; const 在*之前(等價char const * p) 指向常量,指標所指內容不可改,但指標可指向別處。

char * const p; const 在*之後

指標不可改(即不可指向別處),但所指內容可以修改。

const char * const p;指標本身和所指內容都不可改

#include #include using namespace std;

int main()

輸出:

22 2

2 22

常引用:

常引用可用右值初始化

#include #include using namespace std;

int main()

輸出:

3

3 3 1

volatile"

volatile的作用是: 作為指令

關鍵字,確保本條指令不會因

編譯器的優化而省略,且要求每次直接讀值.

簡單地說就是防止

編譯器對**進行優化.比如如下程式:

1

2

3

4

xbyte[2]=0x55;

xbyte[2]=0x56;

xbyte[2]=0x57;

xbyte[2]=0x58;

對外部硬體而言,上述四條語句分別表示不同的操作,會產生四種不同的動作,但是編譯器卻會對上述四條語句進行優化,認為只有

xbyte[2]=0x58(即忽略前三條語句,只產生一條機器**)。如果鍵入volatile,則編譯器會逐一的進行編譯並產生相應的機器**(產生四條

**).

1). 乙個引數既可以是const還可以是volatile嗎?解釋為什麼。

2). 乙個指標可以是volatile 嗎?解釋為什麼。

3). 下面的函式被用來計算某個整數的平方,它能實現預期設計目標嗎?如果不能,試回答存在什麼問題: 1

2

3

4

intsquare(volatileint*ptr)

下面是答案:

1). 是的。乙個例子是唯讀的

狀態暫存器。它是volatile因為它可能被意想不到地改變。它是const因為程式不應該試圖去修改它。

2). 是的。儘管這並不很常見。乙個例子是當乙個中斷服務子程式修改乙個指向乙個buffer的

指標時。

3). 這段**是個惡作劇。這段**的目的是用來返

指標*ptr指向值的平方,但是,由於*ptr指向乙個volatile型引數,

編譯器將產生類似下面的**: 1

2

3

4

5

6

7

intsquare(volatileint*ptr)

由於*ptr的值可能在兩次取值語句之間發生改變,因此a和b可能是不同的。結果,這段**可能返回的不是你所期望的平方值!正確的**如下: 1

2

3

4

5

6

longsquare(volatileint*ptr)

下面我們來乙個個說明。

考慮下面的**:

**:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

classgadget

}

voidwakeup()

//...

private:

boolflag_;

};

上面**中gadget::wait的目的是每過一秒鐘去檢查一下flag_成員

變數,當flag_被另乙個執行緒設為true時,該函式才會返回。至少這是程式作者的意圖,然而,這個wait函式是錯誤的。

假設 編譯器發現sleep(1000)是呼叫乙個外部的庫函式,它不會改變成員

變數flag_,那麼編譯器就可以斷定它可以把flag_快取在

暫存器中,以後可以訪問該暫存器來代替訪問較慢的主機板上的記憶體。這對於

單執行緒**來說是乙個很好的優化,但是在現在這種情況下,它破壞了程式的正確性:當你呼叫了某個gadget的wait函式後,即使另乙個執行緒呼叫了wakeup,wait還是會一直迴圈下去。這是因為flag_的改變沒有反映到快取它的暫存器中去。

編譯器的優化未免有點太……樂觀了。

在大多數情況下,把

變數快取在暫存器中是乙個非常有價值的優化方法,如果不用的話很可惜。c和c++給你提供了顯式禁用這種快取優化的機會。如果你宣告

變數是使用了volatile

修飾符,

編譯器就不會把這個

變數快取在

暫存器裡——每次訪問都將去訪問變數在記憶體中的實際位置。這樣你要對gadget的wait/wakeup做的修改就是給flag_加上正確的修飾:

1

2

3

4

5

6

7

classgadget

;

"

複習知識點

題目 class aclass bextends aclass cextends aclass dextends ba obj newd system.out.println obj instanceofb system.out.println obj instanceofc system.out....

知識點複習

scanf d用於輸入十進位制數 u無符號十進位制輸入 o用於輸入8進製數 c用於輸入單個字元 s用於輸入字串 非空格開始,空格結束,字串變數以 0 結尾 f,lf用於輸入實數,一般使用double,lf 表示對應的輸入量不賦給乙個變數 d printf d帶符號十進位制輸出 u無符號十進位制輸出 ...

C 知識點複習(二)

昨天的複習讓自己有不小的收穫,對一些基礎知識也有了更加深刻的理解,所以今天在昨天的複習基礎上繼續往 後複習,鞏固 1 繼承時的名字遮攔 派生類的成員和基類中的成員重名,那麼就會遮攔從基類繼承過來的成員,派生類在使用該成員時,實際上是派 生類新增的成員,不是從基類中繼承來的 在基類和派生類中,不管是成...