http://blog.csdn.net/btwsmile/article/details/6693178
什么是類型安全?
類型安全很大程度上可以等價於內存安全,類型安全的代碼不會試圖訪問自己沒被授權的內存區域。“類型安全”常被用來形容編程語言,其根據在於該門編程語言是否提供保障類型安全的機制;有的時候也用“類型安全”形容某個程序,判別的標准在於該程序是否隱含類型錯誤。類型安全的編程語言與類型安全的程序之間,沒有必然聯系。好的程序員可以使用類型不那么安全的語言寫出類型相當安全的程序,相反的,差一點兒的程序員可能使用類型相當安全的語言寫出類型不太安全的程序。絕對類型安全的編程語言暫時還沒有。
C語言的類型安全
C只在局部上下文中表現出類型安全,比如試圖從一種結構體的指針轉換成另一種結構體的指針時,編譯器將會報告錯誤,除非使用顯式類型轉換。然而,C中相當多的操作是不安全的。以下是兩個十分常見的例子:
(1)printf格式輸出
- /* - print.cpp
- * version:1.1
- */
- int main()
- {
- printf("%d\n",10);
- system("pause");
- return 0;
- }
上面的代碼很簡單,printf函數中,%d與10匹配,結果正確。
稍作修改:
- /* - print.cpp
- * version:1.2
- */
- int main()
- {
- printf("%f\n",10);
- system("pause");
- return 0;
- }
%f浮點數與10並不匹配,但是編譯通過,執行也沒報錯,但是結果卻是:
0.000000
請按任意鍵繼續. . .
更進一步,把%f修改為%s,編譯通過,執行將報錯Access Violation。
(2)malloc函數的返回值
malloc是C中進行內存分配的函數,它的返回類型是void*即空類型指針,常常有這樣的用法char* pStr=(char*)malloc(100*sizeof(char)),這里明顯做了顯式的類型轉換。類型匹配尚且沒有問題,但是一旦出現int* pInt=(int*)malloc(100*sizeof(char))就很可能帶來一些問題,而這樣的轉換C並不會提示錯誤。
C++的類型安全
如果C++使用得當,它將遠比C更有類型安全性。相比於C,C++提供了一些新的機制保障類型安全:
(1)操作符new返回的指針類型嚴格與對象匹配,而不是void*;
(2)C中很多以void*為參數的函數可以改寫為C++模板函數,而模板是支持類型檢查的;
(3)引入const關鍵字代替#define constants,它是有類型、有作用域的,而#define constants只是簡單的文本替換;
(4)一些#define宏可被改寫為inline函數,結合函數的重載,可在類型安全的前提下支持多種類型,當然改寫為模板也能保證類型安全;
(5)C++提供了dynamic_cast關鍵字,使得轉換過程更加安全,因為dynamic_cast比static_cast涉及更多具體的類型檢查。
即便如此,C++也不是絕對類型安全的編程語言。如果使用不得當,同樣無法保證類型安全。比如下面兩個例子:
- int i=5;
- void* pInt=&i;
- double d=(*(double*)pInt);
- cout<<d<<endl;
輸入結果不是5,而意想不到的結果:-9.25596e+061。又比如:
- #include<iostream>
- using namespace std;
- class Parent
- {
- };
- class Child1:public Parent
- {
- public:
- int i;
- Child1(int e):i(e)
- {
- }
- };
- class Child2:public Parent
- {
- public:
- double d;
- Child2(double e):d(e)
- {
- }
- };
- int main()
- {
- Child1 c1(5);
- Child2 c2(4.1);
- Parent* pp;
- Child1* pc1;
- pp=&c1;
- pc1=(Child1*)pp; //#1 強制轉換,由於類型仍然為Child1*,不造成錯誤
- cout<<pc1->i<<endl;
- pp=&c2;
- pc1=(Child1*)pp; //#2 強制轉換,且類型發生變化,將造成錯誤
- cout<<pc1->i<<endl;
- system("pause");
- return 0;
- }
結果如下:
5
1717986918
請按任意鍵繼續. . .
上面兩個例子之所以引起類型不安全的問題,是因為程序員使用不得當。第一個例子用到了空類型指針void*,第二個例子則是在兩個類型指針之間進行強制轉換。因此,想保證程序的類型安全性,應盡量避免使用空類型指針void*,盡量不對兩種類型指針做強制轉換。