你有花生我有酒,一本學道看一天(二)
技術標籤:cpp大一上題解
五點了啊哈,才看到12頁。
貓頭鷹被花生辣醒了。
提示,各取所需,美美與共,不要硬肝。
斜體下劃線是回答,其他的是背景、解釋、分析甚至吐槽。
目錄
p12 變數定義前的修飾符(續++)
五點整,開盤王者,嘖,金牌法師。咳,來講面向物件中特別會用到的修飾符。
1)型別物件例項/變數 宣告和定義修飾符標識
宣告時修飾符必須顯示標識,定義時如果有預設的修飾符可不顯示標識,但是顯示標識可提高程式可讀性
修飾符(前置修飾)變數 | const | extern | static | volatile |
非自定義類型別中的變數宣告和定義 | 不可修改變數的值;定義時預設為檔案級變數,可通過顯示extern擴充套件 | 指定為宣告;擴充套件變數為多檔案級變數;定義時非const變數預設帶有該標識 | 靜態儲存變數;不可更改的檔案級變數 | 機器因素可更改變數,編譯器不作優化處理 |
2) 自定義類資料成員定義和初始化
修飾符(前置修飾)宣告和初始化 | const | static | volatile | mutable (可在const函式中更改該資料成員) |
宣告時標識 | 所有資料的特殊作用擴充套件都需要在宣告時顯示標識 | |||
初始化時標識 | 必須在建構函式初始化列表中完成初始化 | 需要在類定義體外進行初始化,但不可進行顯示標識 | 可在建構函式初始化列表中初始化,或在建構函式體中進行非初始化賦值 |
p25 邏輯運算子
我發現我搞錯了。
邏輯運算子是可以多個串聯的,例如
if(0||0||0||0||1)
if(x == 0 && x == 3 && y == 2)
都是合法的。
並且由於短路邏輯,以上兩個運算子,在遇到一個使結果成立/不成立的算式時就會停止運算。以第二個舉例,假設int x = 0,那麼x == 0符合,x == 3不符合,則它就不再考慮y的問題,直接返回false即可。
運算子優先順序和iomanip庫輸出格式我是真的記不住。
有點苦惱,直到我想起上機考試可以帶書。
p38 switch,default的特別寫法有點兒玄學,以前搞明白過,我記得很不合自然思路,然後現在也忘了。
p52 二維陣列初始化
a.多維陣列在記憶體中也是連續的;
b.初始化時二維陣列可以只定義第二維大小,第一維可以省略;
c.陣列初始化花括號內包含的第n個花括號指第一維中第n個(俗稱就算是第n行)中初始化的內容;
d.初始化不足的置0。
p58 指標定義運算子優先順序
這個本來沒想寫的,但有個無聊的人寫了挺長一段來講這個,於是就借過來看看,就當是概念關聯的練習了,指路參考部落格連線第二個。
int p; // 普通的int變數
int *p; // 首先從p開始, p先與*結合,表明p是一個指標。然後再與int結合, 表明p指向的是int型別。所以p是一個指向int型別的指標。
int p[3];//p先與[]結合,表明p是一個數組。然後與int結合,表明陣列的元素是int型別的。因此p是一個整型的陣列。
int *p[3];/*[]的優先順序比*高,所以p先與[]結合,表明p是一個數組,再與*結合,表明數組裡的元素是指標。再與int結合,表明指標指向的是int。所以p是一個數組,陣列元素是整型指標(int*)。*/
int (*p)[3];//*這裡的括號,讓p與*先結合。表明p是一個指標。然後再與[]結合,表明指標指向的型別是陣列。再與int結合,表明陣列的元素是int型別的。 所以p是一個指向整型陣列的指標。*/
int **p; //p為典型的二級指標。
int p(int);/*p首先與()結合,表明p是一個函式。進入()分析,說明該函式有一個int型別的引數。再與外面的int結合,表明函式的返回值是一個int。 所以p是一個引數型別為int,返回值為int的函式。*/
int (*p)(int);/*從p處開始,先與指標結合,表明p是一個指標。然後再與()結合,表明該指標指向的是一個函式。然後再與()裡的int結合,表明函式有一個int型別的引數。再與最外層的int結合,表明函式的返回值是int。 這裡的p是一個典型的函式指標。*/
int *(*p(int))[3];/*這個看上去很複雜。從p開始,先與()結合,表明p是一個函式,然後進入(),與int結合,表明函式的引數為int。再與外面的*結合,表明函式的返回值型別是指標。然後再到最外面一層,先與[]結合,表明返回指標指向的是一個數組。再與最外面的*結合,表明陣列的元素是指標,再與最後的int結合,表明陣列的元素指標指向的是int型別。所以p是一個函式, 引數為int, 返回值為指向int* []的指標。*/
哈,考最後這個多好玩,devcpp上你一時半會兒也沒法程式設計來驗證,狗頭了。
p62 字串與指標
這裡說實話我只是隨便搜搜,結果給我驚了個呆呆。
對於以下這個例子:
char str[] = "YewLi_yiwanshangmeishui";
char *p = str;
char *str = "YewLi_xuyaoyourenguanguan";
這兩者看起來非常相似,但本質上是不同的。
最根本的區別是在記憶體中的儲存區域不一樣,字元陣列儲存在全域性資料區或棧區,第二種形式的字串儲存在常量區。全域性資料區和棧區的字串(也包括其他資料)有讀取和寫入的許可權,而常量區的字串(也包括其他資料)只有讀取許可權,沒有寫入許可權。
記憶體許可權的不同導致的一個明顯結果就是,字元陣列在定義後可以讀取和修改每個字元,而對於第二種形式的字串,一旦被定義後就只能讀取不能修改,任何對它的賦值都是錯誤的。
例如:
#include <stdio.h>
int main(){
char *str = "Hello World!";
str = "I love C!"; //正確,可以更改指標變數本身的指向
str[3] = 'P'; //錯誤,不能修改字串中的字元
return 0;
}
這段程式碼能夠正常編譯和連結,但在執行時會出現段錯誤(Segment Fault)或者寫入位置錯誤。
這就解釋了學道上的那個小點,不加const會有警告的原因,警告的好哇。
p74 函式引數傳遞和函式過載
初始化賦值右往左,傳參賦值左往右,害,最近老給人講這個,搞得我都會了。
函式過載作用於名字相同,引數型別或個數不同的函式之間,其他一切都無關。不細講別的了,但總之按照上面那個初始化和複製要求後,過載的函式不能導致某個呼叫會出現無法根據引數情況判斷呼叫哪個函式的情況即可。
參考部落格和網站:https://blog.csdn.net/mrwenzhi/article/details/76649115