資料的儲存和部分注意不到的「隱式轉換」及例題解析

2021-10-06 10:38:39 字數 3265 閱讀 9079

一、常見型別所佔位數及資料範圍

通過上述執行結果可以得出,不同的資料型別占用不同的位元組空間,我們知道計算機是用二進位制位來儲存資料的,而乙個位元組又是八個二進位制位,我們以佔乙個位元組空間的char型別來進行**。

char型別分為有符號char和無符號char,雖然都占用乙個位元組空間即八個二進位制位,但其表示資料範圍不同。

1、有符號char:有符號型別就是採用首位來作為符號位,0表示正,1表示負。其他位表示資料,最大的數是111 1111,最小是000 0000,加上符號位之後,如果符號位為0,那就是0000 0000 ~ 0111 1111,轉換成十進位制數就是0 ~ 127如果符號位為1,這就有點問題了,是1000 0000 ~ 1111 1111嗎,如果是這樣,那1000 0000不是也是0嗎,這不就有正0和負0兩個0了嗎,顯然是不合理的,其實是這樣,應該是1000 0001 ~ 1000 0000,表示的是-1 ~ -128,這就是我們常說的範圍-2^7 ~ 2^7-1,至於為什麼,等下再說。

2、無符號char:所謂無符號就是說我們只表示正數。這樣也就不需要什麼符號位了,八個二進位制位表示的資料範圍為0000 0000 ~ 1111 1111,即0 ~ 255,這沒有什麼可說的。

二、資料的儲存

資料在計算機中是以補碼形式儲存的,正數的補碼就是原碼,負數的補碼是其符號位不變的情況下,資料位取反加1。接著上邊說一下為什麼要用補碼儲存以及補碼為什麼要這樣算。

1、為什麼要用補碼儲存,資料上是這麼說的

(1)補碼儲存可以解決正0和負0的二義性問題。

(2)補碼儲存使得符號位和資料位統一參與運算,簡化了電路,節約成本。

補碼的設計就是依賴了有限位資料運算可能溢位的特點,用補碼儲存的資料運算時,直接丟失溢位位。

關於正0和負0的問題前邊說過,當用補碼儲存之後有乙個有意思的一點是從-1 ~ -127剛好來了個轉置,也不存在-1之前有-0的可能性了。

另外一點,我們用於表示-128的1000 0000和-127也連起來了,1000 0001 - 1 = 1000 0000完全沒有問題。而且-1加一也等於0,1111 1111 + 1 =0000 0000(丟棄溢位位),這也是完全正確的。

2.補碼為什麼要這麼算通過上述描述應該也有所理解了,最妙的一點就在於將負數整體轉置,好巧不巧的有構成了另一特點,正數,0,負數完美的結合了起來。而且最小的負數1000 0000減一等於最大的正數0111 1111,好像在能表示的範圍內構成了乙個環,0->1->最大正數->最小負數->-1->0。這個環形成的原因和對其的理解是很重要的,後邊的好多題目基本都依賴它。

三、可能的「隱式轉換」

課本上所描述的型別之間的隱式轉換是在進行運算時,佔低位元組數的型別的資料自動向高位元組型別的資料轉換,但是我所說的是另外一種,或者說都不能稱之為隱式轉換,更像是由於解碼方式的不同導致的資料改變

舉個例子:

int

main()

這個**細心一點的人就會發現其中的端倪,char型別範圍是-128 ~ 127,所以將a賦給b時,就會出現問題,我們先看一下結果。

出現這一現象,首先想到的是128賦給char型別變數賦不過去,可是真的是賦不過去嗎?我們知道,把乙個佔高位元組的型別資料賦給佔低位元組的型別變數是,可能會發生截斷,使得只儲存低位位元組資料。但是這裡都是佔乙個位元組是不會發生截斷的呀,先看下圖。

無符號字元型128的補碼和有符號字元型-128的補碼完全相同,這就說明並不是賦值錯誤,賦值過去的資料完全相同,只是在解碼時把它作為有符號型別,所以才會出現這樣的結果。

到這裡,總結一下吧:

(1)資料總是以它的補碼存入記憶體,將乙個字面常亮或變數賦值給乙個變數時,存不下就截斷只賦值低位,存的下就賦值過去。

(2)我們所看到的資料發生改變其實都是解碼方式不同的原因,從前到後真實存入記憶體的資料並沒有發生改變。

四、兩個例題

1、

int

main()

結果:

原因是a+b的值是300,直接輸出什麼都不影響,就是300,但是將這個結果賦值給c時,300的補碼是1 0010 1100,賦給c截斷將最高位丟棄,剩餘值正好是44,。

2、

int

main()

printf

("%d\n"

, count)

;}

結果:

這個題和之前說的那個環就有點關係了,a是char型別,範圍是-128 ~ 127,初始值為-1,從-1 ~ -128count加128次,a再減一時a = 127,然後從127 ~ 1count加127次,然後a-1=0,迴圈終止,所以count最終等於255。

Scala的隱式引數和隱式轉換

隱式 implicit 是scala中最重要的內容同時也是最難懂的概念。在scala中隱式的概念主要包括三個方面的內容 1隱式引數 2隱式轉換 3隱式呼叫 首先隱式implicit 是什麼意思?在scala中implicit是在編譯器需要修復型別匹配時,可以用來自動插入的定義。比如舉個例子,我要把2...

Scala中的隱式轉換函式 隱式引數和隱式類

隱式轉換函式 所謂隱式轉換函式指的是implicit關鍵字修飾的且只有乙個引數的函式,其作用是 1.隱式轉換增強現有型別,2.隱式轉換做引數型別轉換 1.例如 inplicit def int2string n int string n.tostring 上案例 我們把fruit物件轉換成了monk...

Hive部分 行式儲存和列式儲存的比較

行式儲存和列式儲存的比較 列式儲存 columnar or column based 是相對於傳統關係型資料庫的行式儲存 row basedstorage 來說的。簡單來說兩者的區別就是如何組織表 row based storage stores atable in a sequence of ro...