位運算和大小端以及位移操作 bitwise & byte Endianness

来源:https://www.cnblogs.com/trancing/archive/2022/04/14/16144952.html
-Advertisement-
Play Games

在實際生活中,很多軟體都支持打開本地磁碟已經存在的圖片,然後進行編輯,編輯完畢後,再重新保存到本地磁碟。如果使用AWT要完成這樣的功能,那麼需要使用到ImageIO這個類,可以操作本地磁碟的圖片文件。 方法名稱 方法功能 static BufferedImage read(File input) 讀 ...


大小端的概念大家都很熟悉了。

這個概念主要是針對 32bit或者 64bit機器中,多個位元組的排列順序

出處

這個詞很奇怪,查了下出處。

The Computer Science terms Big-Endian and Little-Endian were introduced by Danny Cohen 2 in 1980. The key term endian has its roots in the novel Gulliver’s Travels 3 by Jonathan Swift 4 where within a war occurs between two factions who are fighting over which end of a boiled egg should be opened for eating. The big end or the little end. Unsurprisingly, the same said book was the inspiration for the naming of the Gulliver library.

可以看到原出處是一個小說,裡面描述兩股勢力因為 吃水煮蛋應該從雞蛋的哪一端開始吃而發生了戰爭。類似於咸甜豆腐腦的爭端。

Endianness就是指雞蛋的兩頭。作者起這個名字,我猜是想代表位元組序本質上是一個沒有什麼實質意義,卻又真實存在的分歧。

具體區別

一圖流:

大小端的區別

個人覺得小端相對來說比較符合直覺:

高位在高地址,低位在低地址。

引發的問題

主要是在32位(或者64位)的機器上,如何解釋 2位元組或者單位元組的數據。

以及一些強制類型轉換可能出現的問題

bitwise endianness bit內部的大小端

上面討論的是,64位機器內部,8個位元組的順序問題

實際上,對於一個位元組內部的Bit,也存在一個對稱的問題,bit的排列順序是怎麼樣的

給定一個結構體:

struct Byte {
    UINT8 bit0:1;
    UINT8 bit1:1;
    UINT8 bit2:1;
    UINT8 bit3:1;
    UINT8 bit4:1;
    UINT8 bit5:1;
    UINT8 bit6:1;
    UINT8 bit7:1;
};

 問題來了, bit 0 到底是在 Byte的 LSB還是在MSB?換個問的方法,我要修改bit 0, 是 byte |= (1 << 0), 還是 byte |= (1 << 7)

簡而言之的結論:

不確定。

C99 §6.7.2.1, paragraph 10 says:

"The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined."

 

C99標準表示: 具體的bit order和compiler的實現相關。

所以用bit 來表示數據的方式,相容性需要提個醒。

最安全的方式使用結構體內的成員引用方式。

 

如果需要顯式的表示這些位置,最好用下麵的定義方式:

 1 /* Each of these preprocessor directives defines a single bit,
 2    corresponding to one button on the controller.  
 3    Button order matches that of the Nintendo Entertainment System. */
 4 #define KEY_RIGHT  0b00000001
 5 #define KEY_LEFT   0b00000010
 6 #define KEY_DOWN   0b00000100
 7 #define KEY_UP     0b00001000
 8 #define KEY_START  0b00010000
 9 #define KEY_SELECT 0b00100000
10 #define KEY_B      0b01000000
11 #define KEY_A      0b10000000
12 
13 int gameControllerStatus = 0;
14 
15 /* Sets the gameControllerStatus using OR */
16 void KeyPressed( int key ) { gameControllerStatus |= key; }
17 
18 /* Clears the gameControllerStatus  using AND and ~ (binary NOT)*/
19 void KeyReleased( int key ) { gameControllerStatus &= ~key; }
20 
21 /* Tests whether a bit is set using AND */
22 int IsPressed( int key ) { return gameControllerStatus & key; }

 

關於位運算 bitwise operation

用了很多年C,關於左移和右移操作,經常還是搞不清楚到底操作符在哪邊。

這裡一次搞明白

C99的定義:

shift-expression:

  additive-expression

  shift-expression<<additive-expression

  shift-expression>>additive-expression

 

<< 或者 >>的 右側是具體移動的位數,左邊則是被操作數

x = y >> 2; // y 向右移動2位 
x = y << 2; // y 向左移動2位

 

logical shift & arithmic shift 邏輯位移和算數位移

當位移操作和有符號數搞在一起的時候,就需要非常小心。

單純的shift我們稱作logic shift

If the variable ch contains the bit pattern 11100101, then ch >> 1 will produce the result 01110010, and ch >> 2 will produce 00111001.

上面的ch,如果以無符號數來表示,則邏輯位移不會影響語義的表達。

但是如果以有符號數表示,則從一個負數變成了一個正數。如果用作乘法操作就非常危險了。

 

對於C語言,左移和右移是有區別的:

  • 左移永遠都是logical shift

A left shift is always a logical shift (the bits that are shifted off the end are discarded, including the sign bit).

  • 右移,在unsigned時是logical shift,在signed時候是arithmic shift : 即會複製之前的符號位到最高位。

For unsigned numbers, the bit positions that have been vacated by the shift operation are zero-filled. For signed numbers, the sign bit is used to fill the vacated bit positions. In other words, if the number is positive, 0 is used, and if the number is negative, 1 is used.


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、profile的多文檔配置方式 1、profile文件方式:提供多個配置文件,每個代表一種環境 如: 1.application-dev.properties/yml 開發環境 2.application-test.properties/yml 測試環境 3.application-pro.pr ...
  • Java自增 本文分為以下部分: 慄子 慄子解釋 來點複雜的 位元組碼解讀 總結 慄子 java存在一種神奇的操作符,,自增1,但是經常分不清楚 **i** 和**++i** 兩者的區別,雖然最後結果可能都是 i+1,但是在不同場景使用有不同效果。先上一段代碼。 public class Increa ...
  • 今天為大家介紹使用 mitmproxy 這個抓包工具如何監控手機上網,並且通過抓包,把我們想要的數據下載下來。 啟動 mitmproxy 首先我們通過執行命令 mitmweb 啟動mitmproxy,讓它處理監聽狀態,服務會監聽本機 8080 埠,啟動後如下: Python學習交流Q群:90671 ...
  • 前言 今天這個案例,就是控制自己的攝像頭拍照,並且把拍下來的照片,通過郵件發到自己的郵箱里。想完成今天的這個案例,只要記住一個重點:你需要一個攝像頭 思路 通過opencv調用攝像頭拍照保存圖像本地 用email庫構造郵件內容,保存的圖像以附件形式插入郵件內容 用smtplib庫發送郵件到指定郵箱 ...
  • 老闆最近越來越過分了,快下班了發給我幾百個表格讓我把內容合併到一個表格內去。 還好我會Python,分分鐘就搞定了,這要是換個不會Python的,不得加班到第二天天亮去了~ 這麼好用的技能,必須分享給大家,話不多說,咱們直接開始! 準備工作 咱們需要先準備表格數據,會爬蟲的兄弟可以自己爬一點,不會的 ...
  • #Java 從零開始實現一個畫圖板、以及圖像處理功能,代碼可復現 這是一個學習分享博客,帶你從零開始實現一個畫圖板、圖像處理的小項目,為了降低閱讀難度,本博客將畫圖板的一步步迭代優化過程展示給讀者,篇幅較長,Java初學者可放心食用。(文末有源代碼) ##本博客實現的功能(根據本文講解的順序) 直線 ...
  • SDS (Simple Dynamic String)是 Redis 最基礎的數據結構。直譯過來就是”簡單的動態字元串“。Redis 自己實現了一個動態的字元串,而不是直接使用了 C 語言中的字元串。 sds 的數據結構: struct sdshdr { // buf 中已占用空間的長度 int l ...
  • 前言 有沒有小伙伴跟我一樣,最近工作比較繁雜,經常忘事,有時候記了備忘錄結果卻忘記看備忘錄,但是微信是每天都會看的,於 是就想到寫 一個基於微信的提醒系統。總體思路是將待辦事項記錄到線上記事本,通過建立定時任務,每天早上爬取文檔中記 錄 的待辦事項,篩選出當日需要處理的事項,併發送到自己微信。 1任 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...