C語言之數據在內存中的存儲(1),整形與大小端字節序


目錄

前言

一、整形數據在內存中的存儲

二、大小端字節序

三、大小端字節序的判斷

四、字符型數據在內存中的存儲

總結



前言

? ? ?本文主要講述整型包括字符型是如何在內存中存儲的,涉及到大小端字節序這一概念,還有如何判斷大小端,希望對大家有所幫助


??感謝支持,點贊關注不迷路??


(本文內容涉及到整形提升,如不了解,主頁中可查看詳細,兩篇結合起來看更深入)

一、整形數據在內存中的存儲

我們都知道。整數的2進制表示有3種,即原碼、反碼、補碼

? ? ?

有符號的整數,三種表示方法均有符號位和數值位兩部分,符號位都是用0表示“正”,用1表 示“負”,最高位的一位是被當做符號位,剩余的都是數值位。

  • 原碼:直接將數值按照正負數的形式翻譯成二進制得到的就是原碼。
  • 反碼:將原碼的符號位不變,其他位依次按位取反就可以得到反碼。
  • 補碼:反碼+1就得到補碼。

正整數的原、反、補碼都相同。

負整數的三種表示方法各不相同。

對于整形來說:數據存放內存中其實存放的是補碼。

為什么呢?

? ? ?

在計算機系統中,數值?律用補碼來表示和存儲。 原因在于,使用補碼,可以將符號位和數值域統一處理; 同時,加法和減法也可以統一處理(CPU只有加法器)此外,補碼與原碼相互轉換,其運算過程是相同的(都是取反加1),不需要額外的硬件電路。

(主頁·位操作符有詳細舉例)


二、大小端字節序

運行以下代碼,在vs(32位)調試窗口觀察其在內存中的存儲情況

#include <stdio.h>int main()
{int a = 0x11223344;return 0;
}

內存調試窗口:

(0x0058FB3C是a在內存中的首地址)

發現:a = 0x11223344,它在內存中存儲的卻是 44 33 22 11,是倒著存儲的。相信我們平時調試的時候肯定會有這樣的疑問,這就涉及到了大小端字節序了。

什么是大小端?

其實超過一個字節的數據在內存中存儲的時候,就有存儲順序的問題,按照不同的存儲順序,我們分為大端字節序存儲和小端字節序存儲,下面是具體的概念:

  • 大端(存儲)模式: 是指數據的低位字節內容保存在內存的高地址處,而數據的高位字節內容,保存在內存的低地址處。
  • 小端(存儲)模式: 是指數據的低位字節內容保存在內存的低地址處,而數據的高位字節內容,保存在內存的高地址處。

解釋說明:例如上面的 a = 0x11223344,我們按照數學方式讀這個數時,44是不是個位和十位。它相比于前面的 112233?是不是算低位。44?就是一個低位字節內容,VS是以小端模式存儲數據的,所以 44 就存儲在內存的低地址處,其余的就按順序往高處存儲,這樣我們看到的就是 44 33 22 11了。那么假如我們用的是大端模式存儲數據的,那么我們看到的就是 11 22 33 44 ,11在內存中對應的是低地址,44 是高地址。

為什么有大小端?

為什么會有大小端模式之分呢?

? ??

這是因為在計算機系統中,我們是以字節為單位的,每個地址單元都對應著?個字節,?個字節為8 bit 位,但是在C語言中除了8bit的 char 之外,還有16bit的 short 型,32bit的 long 型(要看具體的編譯器),另外,對于位數大于8位的處理器,例如16位或者32位的處理器,由于寄存器寬度大于一個字節,那么必然存在著一個如何將多個字節安排的問題。因此就導致了大端存儲模式和小端存儲模式。

? ? ?

例如:?個 16bit 的 short 型 x ,在內存中的地址為 0x0010,x 的值為 0x1122 ,那么0x11為高字節,0x22為低字節。對于大端模式,就將0x11放在低地址處,即0x0010中,0x22放在高地址處,即0x0011中。小端模式,剛好相反。我們常用的X86 結構是小端模式,而?KEIL C51 則為大端模式。很多的ARM,DSP都為小端模式。有些ARM處理器還可以由硬件來選擇是大端模式還是小端模式。


三、大小端字節序的判斷

判斷大小端其實很簡單,定義 int a = 1,16進制為 0x 00 00 00 01,我們只需要訪問其首地址對應的字節內容即可,小端會以 0x 01 00 00 00 從低地址往高地址排放,大端會以 0x 00 00 00 01 從低地址往高地址排放。

如下,一小段代碼即可:

#include <stdio.h>int check_sys()
{int a = 1;return *(char*)(&a);
}int main()
{int ret = check_sys();if (ret == 1){printf("小端\n");}else if (ret == 0){printf("大端\n");}return 0;
}

運行結果(VS):


四、字符型數據在內存中的存儲

字符型其實也屬于整形范疇,存儲的是其ASCII碼值。

我們可以先觀察以下代碼:

#include <stdio.h>int main()
{char a = -1;signed char b = -1;unsigned char c = -1;printf("a=%d, b=%d, c=%d\n", a, b, c);return 0;
}

運行結果:

解疑:

  1. 首先我們知道,字符型變量以%d打印時是要發生整形提升的。
  2. 然后a為char類型,vs中,char類型默認為有符號字符型,也就是等同于 signed char,所以a整形提升是要看符號位的,-1的補碼是11111111 11111111 11111111 11111111,a大小只有一個字節,存儲時會發生截斷取后8位,a其補碼為11111111,整形提升后 11111111 11111111 11111111 11111111,以%d打印的是原碼,再轉為原碼為10000000 00000000 00000000 00000001,因此打印的還是-1
  3. b與a一樣,然后就是c,c是無符號字符形,c的補碼還是1111111,整形提升,無符號整形提升高位補0,也就是 00000000 00000000 00000000 11111111,再轉為原碼,因為是無符號整形,原反補相同,所以原碼還是 00000000 00000000 00000000 11111111,打印出來就是255。


在看這段代碼:

#include <stdio.h>int main()
{char a = -128;printf("%u\n", a);printf("%d\n", a);return 0;
}

運行結果:

解疑:

  1. 我們發現以%u(無符號整形)方式打印時,打印出的是一個非常大的數字,以%d打印還是原數值,那么為什么會這樣呢
  2. 首先,a以%u打印時,還是會發生整形提升,-128有點大,我們先算出-128的原碼為? 10000000 00000000 00000000 10000000,取反加1算出-128的補碼為 11111111 11111111 11111111 10000000,截斷后 a 的補碼就是10000000,以%u打印,雖然是以無符號整形打印,但是整形提升時是根據原類型進行提升的,原類型為char,有符號字符型,所以高位補符號位1,即 11111111 11111111 11111111 10000000。然后%u就發揮作用了,要把整形提升后的這個補碼看成無符號整形,這時候原反補就相同,原碼就是 1111111 11111111 11111111 10000000,打印出來的結果就是上圖中很大的數字,我們可以借助計算器驗證:
  3. 以%d打印時接著2中整形提升后的補碼 11111111 11111111 11111111 10000000,這里是以%d打印,所以要看成有符號的整形,其原碼就要進行取反加1,即 10000000 00000000 00000000 10000000,打印出來就是-128


再看這段代碼:

#include <stdio.h>int main()
{char a = 128;printf("%u\n", a);printf("%d\n", a);return 0;
}

運行結果:

解疑:

  1. 我們發現128的結果與-128的結果相同,這又是為什么
  2. 其實我們自己再重新算一下就會發現,a存儲時補碼都是 10000000,因為128與-128的補碼后8位是完全相同的,截斷時值就相同。算一個特殊情況,因為a的值相同,所以后續以%u或者%d打印時效果也相同。


通過以上例題,我們可以再推導一下char型變量(有符號)的存儲范圍為啥是 -128~127了,還有 unsigned char 為啥是 0~255

我們畫圖分析:

如此,我們可以畫成一個圓:

這就是 char 類型為什么存儲范圍是-128~127,哪怕賦值的數字超過這個范圍,也會被截斷在這個范圍內。

這就是unsigned char 存儲范圍為什么是0~255。

其實,signed short 和 unsigned short 類型數據也可以畫圓圈表示,int也可以,這里如果感興趣可以自己畫著試試。同上即可


?

總結

? ? ? ? 以上就是本文的全部內容,希望對你有所幫助。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/42195.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/42195.shtml
英文地址,請注明出處:http://en.pswp.cn/web/42195.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2、需求工具 - 編程實戰工具系列文章

需求分析工具 筆者對于需求分析工具的應用&#xff0c;主要是思維導圖軟件和Word。思維導圖用來理清需要的需求功能&#xff0c;而Word用來記錄每個需求功能的實際內容。 對于思維導圖軟件&#xff0c;筆者用過幾個&#xff0c;但是有些需要注冊碼&#xff0c;有些需要費用&…

谷粒商城學習-09-配置Docker阿里云鏡像加速及各種docker問題記錄

文章目錄 一&#xff0c;配置Docker阿里云鏡像加速二&#xff0c;Docker安裝過程中的幾個問題1&#xff0c;安裝報錯&#xff1a;Could not resolve host: mirrorlist.centos.org; Unknown error1.1 檢測虛擬機網絡1.2 重設yum源 2&#xff0c;報錯&#xff1a;Could not fetch…

Redis基礎教程(十五):Redis GEO地理信息查詢與管理

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;歡迎各位來到我的博客&#xff0c;很高興能夠在這里和您見面&#xff01;希望您在這里不僅可以有所收獲&#xff0c;同時也能感受到一份輕松歡樂的氛圍&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…

絕區伍--2024年AI發展路線圖

2024 年將是人工智能具有里程碑意義的一年。隨著新模式、融資輪次和進步以驚人的速度出現&#xff0c;很難跟上人工智能世界發生的一切。讓我們深入了解 2024 年可能定義人工智能的關鍵事件、產品發布、研究突破和趨勢。 2024 年第一季度 2024 年第一季度將推出一些主要車型并…

【React Hooks原理 - useEffect、useLayoutEffect】

介紹 在實際React Hooks項目中&#xff0c;我們需要在項目的不同階段進行一些處理&#xff0c;比如在頁面渲染之前進行dom操作、數據獲取、第三方加載等。在Class Component中存在很多生命周期能讓我們完成這個操作&#xff0c;但是在React Hooks沒有所謂的生命周期&#xff0…

python - 類和對象

一.類 類名用大寫字母開頭 屬性是類中的變量&#xff0c;方法是類中的函數 類、class關鍵字&#xff1a; >>> class Turtle: ... color green ... weight 10 ... legs 4 ... shell True ... mount 大嘴 ... def climb(self): ... …

從零開始讀RocketMq源碼(二)Message的發送詳解

目錄 前言 準備 消息發送方式 深入源碼 消息發送模式 選擇發送方式 同步發送消息 校驗消息體 獲取Topic訂閱信息 高級特性-消息重投 選擇消息隊列-負載均衡 裝載消息體發送消息 壓縮消息內容 構造發送message的請求的Header 更新broker故障信息 異步發送消息 …

Open3D KDtree的建立與使用

目錄 一、概述 1.1kd樹原理 1.2kd樹搜索原理 1.3kd樹構建示例 二、常見的領域搜索方式 2.1K近鄰搜索&#xff08;K-Nearest Neighbors, KNN Search&#xff09; 2.2半徑搜索&#xff08;Radius Search&#xff09; 2.3混合搜索&#xff08;Hybrid Search&#xff09; …

ai native 模型微調

AI native 模型微調&#xff08;fine-tuning&#xff09;是指在預訓練模型的基礎上&#xff0c;通過對其參數進行進一步訓練&#xff0c;使其在特定任務上表現更佳。以下是關于模型微調的一些基本步驟和概念&#xff1a; ### 1. 準備數據集 - **數據收集**&#xff1a;收集適用…

后端之路——登錄校驗前言(Cookie\ Session\ JWT令牌)

前言&#xff1a;Servlet 【登錄校驗】這個功能技術的基礎是【會話技術】&#xff0c;那么在講【會話技術】的時候必然要談到【Cookie】和【Session】這兩個東西&#xff0c;那么在這之前必須要先講一下一個很重要但是很多人都會忽略的一個知識點&#xff1a;【Servlet】 什么是…

Oracle PL/SQL 循環批量執行存儲過程

1. 查詢存儲過程 根據數據字典USER_OBJECTS查詢出所有存儲過程。 2. 動態拼接字符串&#xff08;參數等&#xff09; 根據數據字典USER_ARGUMENTS動態拼接參數。 3. 動態執行 利用EXECUTE IMMEDIATE動態執行無名塊。 4. 輸出執行信息 利用DBMS_OUTPUT.PUT_LINE輸出執行成功與…

Android Gradle 開發與應用 (十): Gradle 腳本最佳實踐

目錄 1. 使用Gradle Kotlin DSL 1.1 什么是Gradle Kotlin DSL 1.2 遷移到Kotlin DSL 1.3 優勢分析 2. 優化依賴管理 2.1 使用依賴版本管理文件 2.2 使用依賴分組 3. 合理使用Gradle插件 3.1 官方插件和自定義插件 3.2 插件管理的最佳實踐 4. 任務配置優化 4.1 使用…

Oracle 19c 統一審計表清理

zabbix 收到SYSAUX表空間告警超過90%告警&#xff0c;最后面給出的清理方法只適合ORACLE 統一審計表的清理&#xff0c;傳統審計表的清理SYS.AUD$不適合&#xff0c;請注意。 SQL> Col tablespace_name for a30 Col used_pct for a10 Set line 120 pages 120 select total.…

STM32實戰篇:閃燈 × 流水燈 × 蜂鳴器

IO引腳初始化 即開展某項活動之前所做的準備工作&#xff0c;對于一個IO引腳來說&#xff0c;在使用它之前必須要做一些參數配置&#xff08;例如&#xff1a;選擇工作模式、速率&#xff09;的工作&#xff08;即IO引腳的初始化&#xff09;。 IO引腳初始化流程 1、使能IO引…

LED燈的呼吸功能

"呼吸功能"通常是指 LED 燈的一種工作模式&#xff0c;它模擬人類的呼吸節奏&#xff0c;即 LED 燈的亮度會周期性地逐漸增強然后逐漸減弱&#xff0c;給人一種 LED 在"呼吸"的感覺。這種效果通常用于指示設備的狀態或者簡單地作為裝飾效果。&#xff08;就…

Spring Boot Security自定義AuthenticationProvider

以下是一個簡單的示例&#xff0c;展示如何使用AuthenticationProvider自定義身份驗證。首先&#xff0c;創建一個繼承自標準AuthenticationProvider的類&#xff0c;并實現authenticate方法。 import com.kamier.security.web.service.MyUser; import org.springframework.se…

【Adobe】Photoshop圖層的使用

Adobe Photoshop(簡稱PS)中的圖層是圖像處理中一個核心概念,它允許用戶以堆疊的方式組織圖像的不同部分,從而實現對圖像的復雜編輯和處理而不影響原始圖像。以下是關于Adobe Photoshop圖層的詳細介紹: 一、圖層的定義 圖層就像是透明的紙張,你可以在上面繪制、添加圖像…

YOLOv10改進 | EIoU、SIoU、WIoU、DIoU、FocusIoU等二十余種損失函數

一、本文介紹 這篇文章介紹了YOLOv10的重大改進&#xff0c;特別是在損失函數方面的創新。它不僅包括了多種IoU損失函數的改進和變體&#xff0c;如SIoU、WIoU、GIoU、DIoU、EIOU、CIoU&#xff0c;還融合了“Focus”思想&#xff0c;創造了一系列新的損失函數。這些組合形式的…

Android Init Language自學筆記

Android Init Language由五個元素組成&#xff1a;Acttions、Commands、Services、Options和Imports。 Actions和Services隱式聲明了一個新的section。所以的Commands和Options都屬于最近聲明的section。 Services具有唯一的名稱&#xff0c;如果重名會報錯。 Actions Acti…

解決Spring Boot中的高可用性設計

解決Spring Boot中的高可用性設計 大家好&#xff0c;我是微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01; 1. 高可用性設計概述 1.1 什么是高可用性&#xff1f; 高可用性指系統在面對各種故障和異常情況時&#xff0c;仍…