上次的多執行緒系列因為某些原因暫時停了,後續會根據實際遇到的問題做一些補充。寫部落格是為了記錄我遇到的問題以及解決,便於自我總結,也幫助遇到這些問題的人。
言歸正傳,本文介紹了c++以及c風格的強制型別轉換的一些注意點。
問題描述:我在做報文解析的時候遇到這個問題:
float x=
32.128f
;float tmp=x*
1000
;unsigned
int ret=
(unsigned
int)tmp;
//不安全轉換,不推薦
這個看起來沒啥問題,我當時**是32128,但最後控制效果是32127,損失了一些精度。
2.先說結論:這得說到浮點數在記憶體中的儲存,科學計數法,
符號位 + 1.******(***是資料位)*2^ooooooo(o是指數字)
也就是說,float x=32.128f
實際上在記憶體中以科學計數法表示,只能做到盡可能近似,而不會完全相等。
此處的x
實際值可能是32.1279971
當x*1000之後,值為32127.9971
,然後強制轉化為unsigned int ,暴力的把小數點後面給乾掉了,導致結果為321227
3.解決方法:
~避免使用這種型別轉換,它是不安全的。
~如果一定要使用的話,請使用double
,原因如下
double x=32.218;
實際上x=32.1280000000000000000012
~double等型別資料是否為0的判斷:
double x;if(
(x-0
)<
1e-10
)//也是科學計數法的儲存只能很接近原始資料的原因
~不同的機器對float的精度不一樣,我用自己的電腦復現那個問題,需要把x*1000000,(可能我的精度比較高吧)
關於c++強制型別轉換問題,主要對static_cast<>
,看一段**:**中有注釋不同型別,可根據需要選擇瀏覽
#include
using std::cout;
using std::endl;
class
parent
//構造
void
show()
protected
:int data_p;};
class
son:
public parent
void
show()
private
:int age;};
class
a//測試int轉class的類
//前面加explicit可避免此情況a(
int d,
double ss)
:data
(d),
s(ss)a(
const a& t)
:data
(t.data),s
(t.s)
void
show()
};intmain()
基本資料型別轉換:
子類和基類之間的轉換:子類指標可以轉基類指標,基類不能轉子類(用dynamic_cast可以,但是轉換後,子類的部分資料未知,不可控)。子類物件轉基類是可以的,但是一般使用指標。總結,向上轉換安全。
如果類的建構函式的引數只有乙個變數
(常量字串不算),那麼就會發生類似int--------->calss
的隱式轉換,要避免這種轉換,可以再建構函式前面申明explicit
結構體我再ubuntu上測試也是可以轉換
執行結果圖如下:
關於c++4種型別轉換的使用,不在說啦,如有錯誤,歡迎指正。
C 隱式型別轉換
c 定義了一組內建型別物件之間的轉換標準,在必要時它們被編譯器隱式的應用到物件上。發生隱式型別轉換的情景 1,在混合型別的算術表示式中 轉換原則 轉換為最寬的資料型別。也可叫,算術轉換。int ival 5 double dval 3.14 ival 被提公升為double型別 ival dval ...
C 隱式型別轉換
眾所周知,c 的基本型別中並非完全的對立,部分資料型別之間是可以進行隱式轉換的。所謂隱式轉換,是指不需要使用者干預,編譯器私下進行的型別轉換行為。很多時候使用者可能都不知道進行了哪些轉換。c 物件導向的多型特性,就是通過父類的型別實現對子類的封裝。通過隱式轉換,你可以直接將乙個子類的物件使用父類的型...
C 隱式型別轉換
c primer 中提到 可以用 單個形參來呼叫 的建構函式定義了從 形參型別 到 該類型別 的乙個隱式轉換。這裡應該注意的是,可以用單個形參進行呼叫 並不是指建構函式只能有乙個形參,而是它可以有多個形參,但那些形參都是有預設實參的。那麼,什麼是 隱式轉換 呢?上面這句話也說了,是從 建構函式形參型...