C/C++中的数据类型转换
文章目錄
- 1 隱式類型轉換
- 1.1 隱式類型轉換的基本概念
- 1.2 隱式類型轉換的發生點
- 1.3 浮點數賦值給整形數分析
- 2 C語言中的強制類型轉換
- 3 C++中的強制類型轉換
- 3.1 static_cast
- 3.2 const_cast
- 3.3 reinterpret_cast
- 3.4 dynamic_cast
- 3.5 類型轉換使用建議
C/C++語言中的數據類型轉換主要有兩種:強制類型轉換和隱式類型轉換。
1 隱式類型轉換
1.1 隱式類型轉換的基本概念
我們首先需要知道,隱式類型轉換是編譯器主動進行的類型轉換。
對于隱式數據類型轉換來說:
- 低類型到高類型的隱式類型轉換是安全的,不會產生截斷。
- 高類型到低類型的隱式類型轉換是不安全的,導致不正確的結果。
- 比如:浮點數賦值給整形時,會發生截斷(小數部分丟失)。
注意: 標準C編譯器的類型檢查是比較寬松的,因此隱式類型轉換可能帶來意外的錯誤。
1.2 隱式類型轉換的發生點
隱式類型轉換的發生點如下:
- 算術運算式中,低類型轉換為高類型。
- 賦值表達式中,表達式的值轉換為左邊變量的類型。
- 函數調用時,實參轉換為形參的類型。
- 函數返回值,return表達式轉換為返回值類型。
安全的隱式類型轉換:
1.3 浮點數賦值給整形數分析
直接賦值:
可以看到,編譯器直接將浮點數截斷。
通過函數調用:
可以看到,函數調用時也是發生了隱式類型轉換,編譯器直接將浮點數進行截斷。
注意:當使用如下語句時printf("%d\n", 3.14);,將得到錯誤的結果。由于是變參,所以編譯器根本不知道是什么類型,不會進行隱式類型轉換。
2 C語言中的強制類型轉換
強制類型轉換的語法:
- (Type)var_name;
- (Type)value;
強制類型轉換的結果:
- 目標類型能夠容納目標值,結果不變。
- 目標類型不能容納目標值:結果將產生截斷。
- 注意:不是所有的強制類型轉換都能成功,當不能進行強制類型轉換時,編譯器將產生錯誤信息。
3 C++中的強制類型轉換
C 方式強制類型轉換存在的問題:
- 過于粗暴:任意類型之間都可以進行轉換,編譯器很難判斷其正確性。
- 難于定位 :在源碼中無法快速定位所有使用強制類型轉換的語句。
問題:強制類型轉換在實際工程中是很難完全避免的!如何進行更加安全可靠的轉換?
C++ 將強制類型轉換分為4種不同的類型: static_cast、const_cast、dynamic_cast、reinterpret_cast。
用法:xxx_cast(Expression)
3.1 static_cast
static_cast強制類型轉換:
- 用于類層次結構中基類(父類)和派生類(子類)之間指針或引用的轉換。上行指針或引用(派生類到基類)轉換安全,下行不安全。
- 用于基本數據類型之間的轉換,如把int轉換成char,把int轉換成enum。這種轉換的安全性也要開發人員來保證。
- 把空指針轉換成目標類型的空指針。
- 把任何類型的表達式轉換成void指針類型。
3.2 const_cast
const_cast強制類型轉換:
- 用于去除變量的只讀屬性。
- 強制轉換的目標類型必須是指針或引用。
3.3 reinterpret_cast
reinterpret_cast強制類型轉換:
- 用于指針類型間的強制轉換。
- 用于整數和指針類型間的強制轉換。
- 引用之間的轉換。
目標類型必須是一個指針、引用、算術類型、函數指針!
忠告:濫用 reinterpret_cast 運算符可能很容易帶來風險。 除非所需轉換本身是低級別的,否則應使用其他強制轉換運算符之一。
#include <iostream>using namespace std;class Animal { public:void cry() {cout << "動物叫" << endl;} };class Cat :public Animal { public:void cry(){cout << "喵喵瞄" << endl;}};class Dog :public Animal { public:void cry(){cout << "汪汪汪" << endl;}};int main(void) {//用法一 數值與指針之間的轉換int* p = reinterpret_cast<int*>(0x99999);int val = reinterpret_cast<int>(p);//用法二 不同類型指針和引用之間的轉換Dog dog1;Animal* a1 = &dog1;a1->cry();Dog* dog1_p = reinterpret_cast<Dog*>(a1);Dog* dog2_p = static_cast<Dog*>(a1); //如果能用static_cast ,static_cast 優先//Cat* cat1_p = static_cast<Cat*>(a1);//Cat* cat2_p = static_cast<Cat*>(dog1_p);//NO! 不同類型指針轉換不能使用static_castCat* cat2_p = reinterpret_cast<Cat*>(dog1_p);Animal& a2 = dog1;Dog& dog3 = reinterpret_cast<Dog&>(a2);//引用強轉用法,不同類型之間的引用也可以轉換dog1_p->cry();dog2_p->cry();cat2_p->cry();system("pause");return 0; }3.4 dynamic_cast
dynamic_cast強制類型轉換:
- 用于有繼承關系的類指針之間轉換。
- 用于有交叉關系的類指針之間的轉換。
- 具有類型檢查的功能。
- 需要虛函數的支持。
dynamic是與繼承相關的類型轉換關鍵字,dynamic_cast要求相關的類中必須有虛函數。用于直接或間接繼承關系的指針(引用之間)。
對于指針:
- 轉換成功:得到目標類型指針。
- 轉換失敗:得到一個空指針。
對于引用:
- 轉換成功:得到目標類型的引用。
- 轉換失敗:得到一個異常操作信息。
編譯器會檢查dynamic_cast的使用是否正確,類型轉換的結果只能在運行階段才能得到。
dynamic的使用:
#include <iostream>using namespace std;class Animal { public:virtual void cry() = 0; };class Cat :public Animal { public:void cry(){cout << "喵喵瞄" << endl;}void play(){cout << "爬爬樹"<<endl;}};class Dog :public Animal { public:void cry(){cout << "汪汪汪" << endl;}void play(){cout << "溜達溜達" << endl;}};void animalPlay(Animal& animal) {animal.cry();try {Dog& pDog = dynamic_cast<Dog&>(animal);pDog.play();}catch (std::bad_cast bc) {cout << "不是狗,那應該是貓" << endl;}try {Cat& pCat = dynamic_cast<Cat&>(animal);pCat.play();}catch (std::bad_cast bc) {cout << "不是貓,那應該是上面的狗" << endl;}}void animalPlay(Animal* animal) {animal->cry();Dog* pDog = dynamic_cast<Dog*>(animal);if (pDog) {pDog->play();}else {//pDog == NULLcout << "不是狗,別騙我!" << endl;}Cat* pCat = dynamic_cast<Cat*>(animal);if (pCat) {pCat->play();}else {//pDog == NULLcout << "不是貓,別騙我!" << endl;} }int main(void) {Dog* dog1 = new Dog();Animal* a1 = dog1;//animalPlay(a1);Dog dog2;animalPlay(dog2);Cat* cat1 = new Cat();Animal* a2 = cat1;//animalPlay(a2);Cat cat2;animalPlay(cat2);system("pause");return 0; }新式類型轉換以C++關鍵字的方式出現:
- 編譯器能夠幫助檢查潛在的問題;
- 非常方便的在代碼中定位;
- 支持動態類型識別(dynamic_cast)。
3.5 類型轉換使用建議
1)static_cast靜態類型轉換,編譯的時c++編譯器會做編譯時的類型檢查;隱式轉換;基本類型轉換,父子類之間合理轉換。
2)若不同類型之間,進行強制類型轉換,用reinterpret_cast<>() 進行重新解釋。建議:C語言中能隱式類型轉換的,在c++中可用 static_cast<>()進行類型轉換。因C++編譯器在編譯檢查一般都能通過;C語言中不能隱式類型轉換的,在c++中可以用 reinterpret_cast<>() 進行強制類型解釋。
總結:static_cast<>()和reinterpret_cast<>() 基本上把C語言中的 強制類型轉換給覆蓋,注意reinterpret_cast<>()很難保證移植性。
3)dynamic_cast<>(),動態類型轉換,安全的虛基類和子類之間轉換;運行時類型檢查。
4)const_cast<>(),去除變量的只讀屬性。
最后的忠告:程序員必須清楚的知道: 要轉的變量,類型轉換前是什么類型,類型轉換后是什么類型,轉換后有什么后果。
C++大牛建議:一般情況下,不建議進行類型轉換;避免進行類型轉換。
參考資料:
總結
以上是生活随笔為你收集整理的C/C++中的数据类型转换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 任务的定义、任务切换的原理及实现
- 下一篇: s3c2440移植MQTT