這章的名字雖然叫C++中的C,但是主體卻是給我們介紹了很多C++中和C中原來不知道的只是,真心感覺C++/C的靈活和偉大。努力學習!
因為C++是向下兼容的,所以大部分的C C++是支持的,但是依然有一些差別。
⑴函數原型:int func(int x,int y,int z);
在C中參數是一定要命名的,但是在C++中參數可以不命名,這是為了給函數預留參數,將來修改時只需要給預留參數命名就可以使用,而不需要改變外部接口。
⑵C中int func();代表的意思是不確定的參數數目,而C++中代表沒有參數的函數。C中沒有參數的函數是int func(void);,C++中不確定參數用int func (...);
⑶C中變量的定義必須在塊開始部分聲明所有變量,而C++允許在作用於內的任意地方定義變量。原則是實時定義變量,什麼時候用什麼時候有定義。
⑷C中類型轉換可以使用float a=float(100);這種形式進行隱式的轉換。在C++中更好的習慣是使用顯示的轉換,使轉換更安全。
靜態轉換(static_cast):用於明確定義的轉化,類似int=0x7fff;long l=static_cast
常量轉換(const_cast):用於const和非const之間的轉換。
重解釋轉換(reinterpret_cast):
#includeusing namespace std; const int sz=100; struct X {int a[sz];}; void print(X* x) { for(int i=0;i a<<' '; cout< (&x); for(int* i=xp;i (xp)); print(&x); return true; }
reinterpret_cast通常是一種不明智的編程方式,但是當必須使用它時,它是非常有用的。
⑸C和C++中的枚舉有所不同,C中不對枚舉進行類型檢查,而C++中需要進行嚴格的類型檢查,將枚舉名字當做是保留字進行檢查。枚舉可以讓表達一件有多種特征的事物變得更清晰。(試圖實現類的功能,C++中很少使用了)
switch選擇器只允許使用整形,如果想要實現字符串選擇器需要使用if-else。
標准C的內建類型(由C++繼承)規范不說明每個內建類型必須有多少位,規范只規定內建類型必須能存儲的最大值和最小值。系統文件limits.h和float.h中定義了不同數據類型可能存儲的最大值和最小值。
說明符:C中有4種內建類型,分別是int、char、float、double。C中又有四種說明符,long、short、signed、unsigned。四種內建類型和四種說明符可以組合搭配使用。
這個程序是用來測試各種內建類型的大小的,同時也說明了哪些可以組合哪些不可以組合。
#includeusing namespace std; int main() { cout<<"short int:"< 4 指針簡介
非常有意思的一個小程序,能幫助理解程序的內存布局:
#includeusing namespace std; int a,b,c; char d,e; void func1(int x,int y) { cout< 5 傳參的兩種方式
⑴按值傳遞:
#includeusing namespace std; //按值傳遞 void func(int x) { cout< ⑵引用傳遞: #includeusing namespace std; //按值傳遞 void func(int* x) { cout<<*x< 運行以上的兩個程序就明白傳值和引用的區別了。 6 void*:
它意味著任何類型的地址都可以間接的引用這個指針。
7變量的作用域:
變量的作用域由變量所在最近的一對括號確定。switch-case中不能定義變量。
8指定存儲空間分配:
⑴全局變量:全局變量在所有的函數體外定義,程序的所有部分都可以使用(甚至文件外的代碼),只要在文件中用extern聲明另一個文件中存在的全局變量,那麼這個文件就可以使用這個變量。
⑵局部變量:寄存器變量,關鍵字register告訴編譯器“盡可能快的訪問這個變量”。最好避免使用。
⑶靜態變量:a 靜態變量在真個程序聲明周期都存在。而且static的初始化只在第一次調用時執行,函數調用之間變量的值保持不變。用這種方式,函數可以記住函數調用之間的一些信息片段。
b static變量的優點是在函數范圍之外它是不可用的,所以它不可能被輕易的改變。這會使錯誤局部化。
#includeusing namespace std; int func() { static int x=0; cout< ⑷外部變量:為了理解外部變量就必須要說明一下連接器,連接器分為兩種連接方式:內部連接和外部連接。內部連接時只對正在編譯的文件創建一片存儲空間,別的文件可以使用相同的標示符或全局變量,連接器不會發現沖突---可以用static指定。 外部連接必須為被編譯過得文件創建一片單獨的存儲空間,一旦創建連接器必須解決所有對這篇存儲空間的引用。全局變量和函數名有外部連接,通過extern聲明,可以從其他文件訪問這些變量和函數。函數之外的所有變量(在C++中除了const)和函數定義默認為外部連接。可以使用static特地強調他們具有內部連接,也可以在定義時使用關鍵字extern顯示的指定標示符具有外部連接。在C中,不必用extern定義變量或函數,但是在C++中對於const有時必須使用。
⑸常量:const定義常量,在C++中const只不過是一個標記,意思是“不要改變我”,必須初始化,後續詳細。
9 宏定義簡介:
#define PRINT(STR,VAR)\ cout<可以讓輸入更簡單(避免輸入錯誤); 10 位運算符:(速率最快,一次位操作相當於一個機器指令)
#include^異或:表示兩者真值不同。using namespace std; void printBinary(const unsigned char); #define PR(STR,VAR)\ cout< =0;i--) { if(var & 1<>getval; a=getval; PR("a in binary:",a); return true; } 11 sizeof()-----獨立運算符
提供對於有關數據項目分配內存的大小。
12 asm允許C++調用匯編語言。
13 typedef:
長的數據類型或者函數類型可以使用typedef進行重命名。
14 union:
當想用一個對象處理不同種數據類型時,可以使用union節省內存。
#includeusing namespace std; union pack{ char i; int j; short k; }; int main() { cout<<"sizeof(pack) ="< 去掉pack中的元素,看看union的大小變化。 15 數組的指針:(很有趣!)
#includeusing namespace std; void func1(char* pArray1) { cout<<"char*:"<<(long)pArray1< 運行一下這個程序,仔細的會發現((&array)+1)和其他的地址不一樣。這是因為&array的類型是char*[3],+1是加了一個該類型的長度,也就是3。
16 #
在表達式之前加“#”可以把任何一個表達式轉換成一個字符數組。
17 調試
可以用#define DEBG
#ifdefine DEBUG
/*debug code*/
#endif 的形式來進行程序的調試。
18 assert:
cassert.h中定義的assert宏可以幫助我們調試程序,int i=100;assert(i!=100);斷言為false,程序終止。通過在#include
前加入#define NDEBUG可以消除宏產生的代碼。 19 復雜的聲明和定義:
/*1*/void *(*(*fp1)(int))[10]; /*2*/float (*(*fp2)(int,int,float))(int); /*3*/typedef double (*(*(*fp3)())[10])();這些都是什麼類型,自己試著看幾遍就知道了。得仔細點!20指向函數的指針數組:
一段程序說明問題:
#include#include using namespace std; #define DF(N) void N(){ \ cout<<"fucntiong "#N" called..."< >strCmd) { if(!strCmd.compare("copy")) { (*func_table[0])(); } else if(!strCmd.compare("quit")) { break; } else { cout<<"command is invalid"< 21makefile----簡化工作的工具:
project file其實也是一種Makefile。
我的博客裡有一章專門講makefile。