精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

計算機系統對數值類型的編碼、運算、轉換原理介紹1

jf_78858299 ? 來源:元閏子的邀請 ? 作者:元閏子 ? 2023-05-09 16:30 ? 次閱讀

前言

在日常編程中, 數值類型numeric types )是我們打交道最多的類型,可能沒有之一。除了最熟悉的 int,還有 longfloatdouble 等。正因太熟悉,我們往往不會深究它們的底層原理。因為平時的工作中,知道個大概,也夠用了。

但,在某些業務場景下,比如金融業務,數值運算不準確會帶來災難性的后果。這時,你就必須清楚數值類型的二進制表示、截斷、轉型等原理,否則很難保證運算結果的正確性。

另外,數值類型也是一個容易被黑客攻擊的點,考慮如下一段代碼:

// C++
/* Declaration of library function memcpy */
void *memcpy(void *dest, void *src, size_t n);
/* Kernel memory region holding user-accessible data */
#define KSIZE 1024
char kbuf[KSIZE];
/* Copy at most maxlen bytes from kernel region to user buffer */
int copy_from_kernel(void *user_dest, int maxlen) {
    /* Byte count len is minimum of buffer size and maxlen */
    int len = KSIZE < maxlen ? KSIZE : maxlen;
    memcpy(user_dest, kbuf, len);
    return len;
}

如果你熟悉數值類型的原理,一定會敏銳察覺出第 10 行存在 intsize_t 的類型轉換。在 64 位系統中,size_t 通常被定義為 unsigned long 類型,如果攻擊者在調用 copy_from_kernel 時,特意傳入一個負數的 maxlen,轉型到 memcpy 中的 n 將會是一個很大的正數,從而導致了內存拷貝的越界!

數值類型是計算機編程的基礎,用的很多,也很重要,理解它的底層原理,有助于寫出正確的代碼,避免一些意料之外的錯誤

每個計算機系統都有固定的 word size ,也即常說的 xx 位,它也是指針的大小,跟 虛擬內存 相關,比如一個 w 位系統上的應用程序,最多能夠訪問 byte 大小的虛擬內存。

最常用的是 32 位 和 64 位 系統,某些數值類型在它們之上會有些差異,比如 long 類型 在 32 位系統上是 32 bit 大小,在 64 位系統上是 64 bit 大小。 考慮如今 64 位系統逐漸成為主流,本文會以它作為基礎,進行數值類型的介紹

整數

在計算機系統中,整數可以分成 無符號unsigned )整數 和 有符號signed )整數 兩大類,這之下,按照類型表示的 bit 位大小,又可細分成 8 位的 char/byte/int8 、16 位的 short/innt16、32 位的 int/int32 和 64 位的 long/int64,它們的取值范圍如下:

類型 最小值 最大值
[signed] char -128 127
unsigned char 0 255
short -32,768 32,767
unsigned short 0 65,535
int ?2,147,483,648 2,147,483,647
unsigned int 0 4,294,967,295
long ?9,223,372,036,854,775,808 9,223,372,036,854,775,807
unsigned long 0 18,446,744,073,709,551,615

死記這個表不容易,下面我們將試圖從二進制編碼層面去理解它。

二進制編碼

整數在計算機系統上都是以二進制存儲的,對于一個 w 位的整數 ,它的二進制表示寫成這樣:

其中, 取值 或 。

無符號編碼(Unsigned Encodings)

在二進制表示的基礎上,無符號編碼 是這樣:

比如,w = 4 場景下的一些例子:

圖片

由上述可知, 無符號編碼無法表示負數,因此只能表示無符號整數 。為了表示有符號整數,還要探尋另一種編碼方式。

原碼編碼(True Form Encodings)

為了區分正數和負數,很容易想到使用一個 bit 位作為 符號位 , 表示正數, 表示負數。在無符號編碼的基礎上,使用最高位作為符號位,其他位含義不變,得出 原碼編碼 形式:

比如,w = 4 場景下的一些例子:

圖片

雖然原碼編碼方式簡單直觀,但它還存在兩個問題:

(1) 存在兩種編碼形式

原碼編碼方式下, 存在兩種編碼形式, 和 。同一個整數值,卻有兩種編碼,這對計算機系統來說沒什么意義,反而是一種浪費。

(2)帶負數的加法運算不正確

原碼編碼方式下,兩個正數的加法沒問題,一旦帶上負數,結果就出錯了:

圖片

所以,原碼編碼方式,注定不會被使用。

補碼編碼(Two's-complement Encodings)

于是,補碼編碼 被發明,它也是建立在無符號編碼的基礎上,仍然取最高位為符號位,編碼方式是這樣:

它與無符號編碼的唯一區別是,最高位的取值從 變成了

比如,w = 4 場景下的一些例子:

圖片

補碼編碼很巧妙地解決了原碼編碼的兩個問題:

首先,0 在補碼編碼下只有一種編碼形式, 。

此外,帶負數的加法運算,也正確了。

圖片

因為補碼編碼的簡單和正確性,目前,幾乎所有的計算機系統,都采用補碼編碼來表示有符號整數

位運算

位運算主要包含 取反異或移位 等幾種,我們在業務開發時用得比較少,但如果你有閱讀開源代碼的習慣,就會經常發現它們的蹤跡。如果碰巧對位運算不熟悉,那么閱讀這些代碼,就同讀天書一般。

取反(~)、與(&)、或(|)、異或(^)的規則比較簡單:

圖片

移位運算,可以分成 左移右移 兩種,其中,右移又可分為 邏輯右移算術右移

左移(<<)運算,是對二進制整數,向左移若干位,高位丟棄,低位補零 。也即,對 左移 位,得到 。

比如,對 int i = -1 左移 10 位,會得到 i = -1024 的結果:

// Java語言
public static void main(String[] args) {
    int i = -1;
    System.out.println("Before << , i's value is " + i);
    System.out.println("i's binary string is " + Integer.toBinaryString(i));
    i <<= 10;
    System.out.println("After << , i's value is " + i);
    System.out.println("i's binary string is " + Integer.toBinaryString(i));
}
// 輸出結果:
Before << , i's value is -1
i's binary string is 11111111111111111111111111111111
After << , i's value is -1024
i's binary string is 11111111111111111111110000000000

圖片

在 C/C++ 中,兩種右移操作符都是 >>,對無符號整數用的是邏輯右移,對有符號整數用的是算術右移;在 Java 中,邏輯右移的操作符是 >>>,算術右移的操作符是 >>。為了方便區分,下文統一用 Java 的表示方法。

邏輯右移(>>>)運算,是對二進制整數,向右移若干位,高位補零,低位丟棄 。也即,對 邏輯左移 k 位,得到 。

比如,對 int i = -1 邏輯右移 10 位,會得到 i = 4194303 的結果:

// Java語言
public static void main(String[] args) {
    int i = -1;
    System.out.println("Before >>> , i's value is " + i);
    System.out.println("i's binary string is " + Integer.toBinaryString(i));
    i >>>= 10;
    System.out.println("After >>> , i's value is " + i);
    System.out.println("i's binary string is " + Integer.toBinaryString(i));
}
// 輸出結果:
Before >>> , i's value is -1
i's binary string is 11111111111111111111111111111111
After >>> , i's value is 4194303
i's binary string is 1111111111111111111111

圖片

算術右移(>>)運算,是對二進制整數,向右移若干位,高位補符號位,低位丟棄 。也即,對 邏輯左移 k 位,得到 。

比如,對 int i = -1 算術右移 10 位,仍會得到 i = -1 的結果:

// Java語言
public static void main(String[] args) {
    int i = -1;
    System.out.println("Before >> , i's value is " + i);
    System.out.println("i's binary string is " + Integer.toBinaryString(i));
    i >>= 10;
    System.out.println("After >> , i's value is " + i);
    System.out.println("i's binary string is " + Integer.toBinaryString(i));
}
// 輸出結果:
Before >> , i's value is -1
i's binary string is 11111111111111111111111111111111
After >> , i's value is -1
i's binary string is 11111111111111111111111111111111

圖片

目前為止,介紹移位運算的原理時,我們都默認 k < w,如果 k >= w 會怎樣

比如, 左移 w 位,結果會是 嗎:

// Java語言
public static void main(String[] args) {
    int i1 = -1;
    System.out.println("Before << 31, i1's value is " + i1);
    System.out.println("i1's binary string is " + Integer.toBinaryString(i1));
    i1 <<= 31;
    System.out.println("After << 31, i1's value is " + i1);
    System.out.println("i1's binary string is " + Integer.toBinaryString(i1));

    int i2 = -1;
    System.out.println("Before << 32, i2's value is " + i2);
    System.out.println("i2's binary string is " + Integer.toBinaryString(i2));
    i2 <<= 32;
    System.out.println("After << 32, i2's value is " + i2);
    System.out.println("i2's binary string is " + Integer.toBinaryString(i2));
}
// 輸出結果:
Before << 31, i1's value is -1
i1's binary string is 11111111111111111111111111111111
After << 31, i1's value is -2147483648
i1's binary string is 10000000000000000000000000000000
Before << 32, i2's value is -1
i2's binary string is 11111111111111111111111111111111
After << 32, i2's value is -1
i2's binary string is 11111111111111111111111111111111

圖片

上述例子中, w = 32,我們發現 k = 31 時,結果還符合預期;當 k = 32 時,結果不是 0,而是 -1,也即相當于 k = 0 時的結果。

原因是這樣,w 位整數 x,當執行 x << k 時,實際執行的是 x << (k % w)。所以,當 i2 << 32 時,實際是 i2 << 32 % 32 = i2 << 0

右移操作也遵循同樣的規則,也即 x >> k = x >> (k % w)x >>> k = x >>> (k % w)

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 二進制
    +關注

    關注

    2

    文章

    794

    瀏覽量

    41600
  • 計算機
    +關注

    關注

    19

    文章

    7425

    瀏覽量

    87722
  • 編程
    +關注

    關注

    88

    文章

    3595

    瀏覽量

    93602
  • 數值
    +關注

    關注

    0

    文章

    80

    瀏覽量

    14352
收藏 人收藏

    評論

    相關推薦

    計算機系統結構

    計算機系統結構
    發表于 05-09 19:03

    什么是計算機系統計算機硬件和計算機軟件?

    第一章 計算機系統概論1. 什么是計算機系統計算機硬件和計算機軟件?硬件和軟件哪個更重要?解:P3計算
    發表于 07-22 09:06

    什么是計算機系統?硬件和軟件哪個更重要?

    第一章計算機系統概論1 .什么是計算機系統計算機硬件和計算機軟件?硬件和軟件哪個更重要?解: P3計算
    發表于 07-26 07:18

    計算機系統中的軟件系統

    專用計算機現代計算機運算速度最高可達每秒幾萬億次幾十億次幾億次幾萬次計算機輔助制造是計算機應用領域之一其英文縮寫是所謂的信息是指基本素材非數值
    發表于 09-13 07:22

    嵌入式計算機系統概述

    硬件子系統和軟件子系統組成的,通過運行程序來協同工作計算機硬件:基本的計算機硬件系統運算器、控
    發表于 12-22 06:08

    簡單介紹微型計算機的組成

    你了解自己的計算機?或者知道單片機的組成嗎?這一小節主要簡單介紹微型計算機的組成,以及微型計算機系統經常用到的概念,包括組成、工作過程、工作原理、
    發表于 01-10 07:11

    計算機系統概論

    1.1 計算機系統簡介1.2 計算機的基本組成1.3 計算機硬件的主要技術指標1.4 本書結構
    發表于 04-11 09:31 ?0次下載

    微型計算機系統

             微型計算機系統與傳統的計算機系統一樣,也是由硬件系統和軟件系統兩大部分組成的。2.1
    發表于 03-03 08:31 ?0次下載

    什么是計算機系統的容錯性

    什么是計算機系統的容錯性             所謂容錯是指在故障存在的情況下計算機系統不失效,仍然能夠正常工作的特性
    發表于 01-08 13:49 ?1628次閱讀

    深入理解計算機系統數值類型

    計算機系統中,整數可以分成 無符號(unsigned)整數 和 有符號(signed)整數 兩大類,這之下,按照類型表示的 bit 位大小,又可細分成 8 位的 char/byte/int8
    的頭像 發表于 08-19 15:17 ?1150次閱讀

    計算機系統對數值類型編碼運算轉換原理介紹2

    。正因太熟悉,我們往往不會深究它們的底層原理。因為平時的工作中,知道個大概,也夠用了。 但,在某些業務場景下,比如金融業務,數值運算不準確會帶來災難性的后果。這時,你就必須清楚數值類型
    的頭像 發表于 05-09 16:31 ?878次閱讀
    <b class='flag-5'>計算機系統</b><b class='flag-5'>對數值</b><b class='flag-5'>類型</b>的<b class='flag-5'>編碼</b>、<b class='flag-5'>運算</b>、<b class='flag-5'>轉換</b>原理<b class='flag-5'>介紹</b>2

    計算機系統對數值類型編碼運算轉換原理介紹3

    。正因太熟悉,我們往往不會深究它們的底層原理。因為平時的工作中,知道個大概,也夠用了。 但,在某些業務場景下,比如金融業務,數值運算不準確會帶來災難性的后果。這時,你就必須清楚數值類型
    的頭像 發表于 05-09 16:31 ?794次閱讀
    <b class='flag-5'>計算機系統</b><b class='flag-5'>對數值</b><b class='flag-5'>類型</b>的<b class='flag-5'>編碼</b>、<b class='flag-5'>運算</b>、<b class='flag-5'>轉換</b>原理<b class='flag-5'>介紹</b>3

    計算機系統對數值類型編碼運算轉換原理介紹4

    。正因太熟悉,我們往往不會深究它們的底層原理。因為平時的工作中,知道個大概,也夠用了。 但,在某些業務場景下,比如金融業務,數值運算不準確會帶來災難性的后果。這時,你就必須清楚數值類型
    的頭像 發表于 05-09 16:31 ?491次閱讀
    <b class='flag-5'>計算機系統</b><b class='flag-5'>對數值</b><b class='flag-5'>類型</b>的<b class='flag-5'>編碼</b>、<b class='flag-5'>運算</b>、<b class='flag-5'>轉換</b>原理<b class='flag-5'>介紹</b>4

    計算機系統中的關鍵組件有哪些

    計算機系統中,關鍵組件的協同工作構成了其強大的數據處理和運算能力。這些組件不僅決定了計算機的性能,還影響著用戶的使用體驗。以下是對計算機系統中關鍵組件的詳細闡述,包括它們的定義、功能
    的頭像 發表于 07-15 18:18 ?1294次閱讀

    微處理器如何控制計算機系統

    微處理器,作為計算機系統的核心部件,承擔著控制整個計算機系統運行的重要任務。它不僅是計算機運算中心,還是控制中心,負責執行程序指令、處理數據以及協調
    的頭像 發表于 08-22 14:21 ?444次閱讀