【C語言】深度剖析數據在內存中的存儲

一、數據類型詳細介紹

1、數據類型介紹

(1)基本的內置類型
//內置類型就是C語言自帶的類型char ? ? ? ?//字符數據類型
short ? ? ? //短整型
int ? ? ? ? //整形
long ? ? ? ?//長整型
long long ? //更長的整形
float ? ? ? //單精度浮點數
double ? ? ?//雙精度浮點數

:C語言中沒有字符串類型。

(2)類型的意義
  • 使用這個類型開辟內存空間的大小(大小決定了使用范圍)。
  • 如何看待內存空間的視角。

2、類型的基本歸類?

(1)整型
charunsigned charsigned charshortunsigned short [int]signed short [int]intunsigned intsigned intlongunsigned long [int]signed long [int]
(2)浮點數
float
double
(3)構造類型
> 數組類型
> 結構體類型 struct
> 枚舉類型 enum
> 聯合類型 union
(4)指針類型
int* pi;
char* pc;
float* pf;
void* pv;
(5)空類型

void表示空類型(無類型)

通常應用于函數的返回類型、函數的參數、指針類型


二、整型在內存中的存儲

?原碼、反碼、補碼

計算機中的有符號數有三種表示方法,即原碼、反碼和補碼

三種表示方法均有符號位和數值位兩部分,符號位都是用 0 表示 “正”,用 1 表示 “負”,而數值位三種表示方法各不相同

?原碼

直接將二進制按照正負數的形式翻譯成二進制就可以。

?反碼

將原碼的符號位不變其他位依次按位取反就可以得到了。

?補碼

反碼 +1 就得到補碼


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


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


為什么在計算機系統中,數值一律用補碼來表示和存儲呢?

原因在于,使用補碼,可以將符號位和數值域統一處理;同時,加法和減法也可以統一處理(CPU只有加法器)此外,補碼與原碼相互轉換,其運算過程是相同的,不需要額外的硬件電路。

在內存中的存儲:?

?

?

補碼:1111 1111 1111 1111?1111 1111 1111 0110 (-10的補碼)
f? ? ? ? f? ? ?? f? ? ? ?f? ? ? ?f? ? ? ? f? ? ? ?f? ? ? 6(-10的十六進制)
我們可以看到對于 a b 分別存儲的是補碼。但是我們發現順序有點 不對勁, ?這是為什么呢?

三、大小端介紹

1、什么是大小端

  • 大端(存儲)模式,是指數據的低位保存在內存的高地址中,而數據的高位,保存在內存的低地址中
  • 小端(存儲)模式,是指數據的低位保存在內存的低地址中,而數據的高位,,保存在內存的高地址中

?


2、為什么會有大端和小端呢??

????????這是因為在計算機系統中,是以字節為單位的,每個地址單元都對應著一個字節,一個字節為 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 處理器還可以由硬件來選擇是大端模式還是小端模式。

下面這段代碼會輸出什么呢??

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

?

幫助理解:?

:char 是 signed char 還是 unsigned char。C 語言并沒有規定,取決于編譯器(大多數編譯器下是 signed char)。


四、浮點型在內存中的存儲

1、常見的浮點數

3.14159 1E10 浮點數家族包括: float double long double 類型。
浮點數表示的范圍: float.h 中定義。????????????

2、標準規定?

根據國際標準?IEEE(電氣和電子工程協會) 754,任意一個二進制浮點數V可以表示成下面的形式(了解即可):

  • (-1)^S * M * 2^E
  • (-1)^S?表示符號位當 S=0,V為正數;當 S=1,V為負數
  • M?表示有效數字大于等于1,小于2
  • 2^E?表示指數位
舉例來說:
十進制的? 5.0 ,寫成二進制是 101.0 ,相當于 1.01×2^2 。 那么,按照上面 V 的格式,可以得出S =0 ,M=1.01, E=2
十進制的? -5.0 ,寫成二進制是 - 101.0 ,相當于 - 1.01×2^2 。那么,S =1 M=1.01 E=2
IEEE 754 規定:
對于? 32? 位的浮點數, 最高的?1?位是符號位 S,接著的?8?位是指數?E,剩下的?23?位為有效數字M

對于64位的浮點數,最高的1位是符號位S,接著的11位是指數E,剩下的52位為有效數字M

????????IEEE 754對有效數字 M 和指數 E ,還有一些特別規定。 前面說過, 1≤M<2 ,也就是說, M 可以寫成 1.xxxxxx 的形式,其中 xxxxxx? 表示小數部分。
????????IEEE 754規定,在計算機內部保存 M 時,默認這個數的第一位總是 1 ,因此可以被舍去,只保存后面的? xxxxxx? 部分。比如保存 1.01? 的時候,只保存? 01 ,等到讀取的時候,再把第一位的 1 加上去。這樣做的目的,是節省 1 位有效數字。以32 位浮點數為例,留給 M 只有 23 位,將第一位的 1 舍去以后,等于可以保存 24 位有效數字。
至于指數 E ,情況就比較復雜。
????????首先, E為一個無符號整數(unsigned int 這意味著,如果 E? 為? 8 位,它的取值范圍為? 0~255 ;如果? E? 11 位,它的取值范圍為 0~2047 。但是,科學計數法中的? E? 是可以出現負數的,所以 IEEE 754? 規定,存入內存時? E? 的真實值必須再加上一個中間數,對于 8? 位的? E ,這個中間數是 127 ;對于? 11? 位的? E ,這個中間數是? 1023 。比如, 2^10? 的? E 是 10 ,所以保存成? 32? 位浮點數時,必須保存成? 10+127=137 ,即 10001001。

然后,指數E從內存中取出還可以再分成種情況:

?E 不全為 0 或不全為 1
這時,浮點數就采用下面的規則表示,即指數? E? 的計算值減去? 127 (或 1023 ),得到真實值,再將有效數字? M? 前加上第一位的 1 。 比如: 0.5 1/2 )的二進制形式為? 0.1 ,由于規定正數部分必須為? 1 ,即將小數點右移? 1 位,則為? 1.0*2^(-1) ,其階碼為? -1+127=126 ,表示為 01111110 ,而尾數? 1.0? 去掉整數部分為? 0 ,補齊? 0? 到? 23 位 00000000000000000000000 ,則其二進制表示形式為
0 01111110 00000000000000000000000
?E全為0
這時,浮點數的指數 E 等于 1~127(或者 1~1023 )即為真實值,
有效數字 M 不再加上第一位的 1,而是還原為 0.xxxxxx 的小數。這樣做是為了表示 ±0,以及接近于 0 的很小的數字。

?E全為1

這時,如果有效數字 M 全為 0,表示 ±無窮大(正負取決于符號位S);

浮點數存儲的例子:

int main()
{int n = 9; //以整型的視角放入float *pFloat = (float *)&n;printf("n的值為:%d\n",n); //以整型的視角拿出printf("*pFloat的值為:%f\n",*pFloat); //以浮點型的視角拿出*pFloat = 9.0; //以浮點型的視角放入printf("num的值為:%d\n",n); //以整型的視角拿出printf("*pFloat的值為:%f\n",*pFloat); //以浮點型的視角拿出return 0;
}

?

?num 和 *pFloat 在內存中明明是同一個數,為什么浮點數和整數的解讀結果會差別這么大?

?分析如下:

?

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

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

相關文章

微信小程序使用rich-text解析富文本字符串的時候,遇到image標簽圖片很大超過屏幕

場景&#xff1a; 使用uniapp開發微信小程序&#xff0c;解析富文本文章需求 用到的組件&#xff1a; u-view2.0的u-parse uniapp提供的rich-text 以上兩種組件都是解析富文本的作用&#xff0c;一般用于富文本解析場景&#xff0c;比如解析文章內容&#xff0c;商品詳情&am…

桶排序-1184:明明的隨機數

【題目描述】 明明想在學校中請一些同學一起做一項問卷調查&#xff0c;為了實驗的客觀性&#xff0c;他先用計算機生成了N個1到1000之間的隨機整數&#xff08;N≤100&#xff09;&#xff0c;對于其中重復的數字&#xff0c;只保留一個&#xff0c;把其余相同的數去掉&#x…

安防監控視頻匯聚平臺EasyCVR分發的FLV視頻流在VLC中無法播放是什么原因?

眾所周知&#xff0c;TSINGSEE青犀視頻匯聚平臺EasyCVR可支持多協議方式接入&#xff0c;包括主流標準協議國標GB28181、RTSP/Onvif、RTMP等&#xff0c;以及廠家私有協議與SDK接入&#xff0c;包括海康Ehome、海大宇等設備的SDK等。在視頻流的處理與分發上&#xff0c;視頻監控…

【jvm】jvm的生命周期

目錄 一、啟動二、執行三、退出 一、啟動 1.java虛擬機的啟動是通過引導類加載器bootstrap class loader創建一個初始類&#xff08;initial class&#xff09;來完成的&#xff0c;這個類是由虛擬機的具體實現指定的(根據具體虛擬機的類型) 二、執行 1.一個運行中的java虛擬機…

ORACLE行轉列、列轉行實現方式及案例

ORACLE行轉列、列轉行實現方式及案例 行轉列案例方式1.PIVOT方式2.MAX和DECODE方式3.CASE WHEN和GROUP BY 列轉行案例方式1.UNPIVOT方式2.UNION ALL 行轉列 案例 假設我們有一個名為sales的表&#xff0c;其中包含了產品銷售數據。表中有三列&#xff1a;product&#xff08;…

FPGA實踐 ——Verilog基本實驗步驟演示

0x00 回顧&#xff1a;AND/OR/NOT 邏輯的特性 AND&#xff1a;與門可以具有兩個或更多的輸入&#xff0c;并返回一個輸出。當所有輸入值都為 1 時&#xff0c;輸出值為 1。如果輸入值中有任何一個為 0&#xff0c;則輸出值為 0。 OR&#xff1a;或門可以具有兩個或更多的輸入…

【python】-【】

文章目錄 轉義字符和原字符二進制與字符編碼標識符和保留字變量的定義和使用變量字符串列表for 一、print會輸出①數字②字符串&#xff08;必須加引號&#xff09;③含有運算符的表達式&#xff08;例如 31 其中3&#xff0c;1是操作數&#xff0c;是運算符&#xff09;&#…

vector的模擬實現

什么是vector vector是一個封裝了動態大小數組的順序容器跟任意其它類型容器一樣&#xff0c;它能夠存放各種類型的對象。 模擬實現 實現前的準備 在實現vector之前&#xff0c;為了和庫里的區分開需要將實現的vector放在一個自定義的命名空間里。而且vector需要實現成模版…

論文閱讀 - Neutral bots probe political bias on social media

論文鏈接&#xff1a;Neutral bots probe political bias on social media | EndNote Click 試圖遏制濫用行為和錯誤信息的社交媒體平臺被指責存在政治偏見。我們部署中立的社交機器人&#xff0c;它們開始關注 Twitter 上的不同新聞源&#xff0c;并跟蹤它們以探究平臺機制與用…

超導熱催生meme,換湯不換藥的投機輪回

文/章魚哥 出品/陀螺財經 幣圈對炒作meme概念的熱情從未消亡過。 隨著一種名為LK-99的物質被發現&#xff0c;圍繞超導的興奮不僅激發了科學界&#xff0c;加密貨幣相關概念也與之沸騰。不出所料&#xff0c;與此前圍繞元宇宙、AI大肆炒作一樣&#xff0c;許多meme代幣已經出現…

關于MySQL中的binlog

介紹 undo log 和 redo log是由Inno DB存儲引擎生成的。 在MySQL服務器架構中&#xff0c;分為三層&#xff1a;連接層、服務層&#xff08;server層&#xff09;、執行層&#xff08;存儲引擎層&#xff09; bin log 是 binary log的縮寫&#xff0c;即二進制日志。 MySQL…

android開發之Android 自定義滑動解鎖View

自定義滑動解鎖View 需求如下&#xff1a; 近期需要做一個類似屏幕滑動解鎖的功能&#xff0c;右劃開始&#xff0c;左劃暫停。 需求效果圖如下 實現效果展示 自定義view如下 /** Desc 自定義滑動解鎖View Author ZY Mail sunnyfor98gmail.com Date 2021/5/17 11:52 *…

數據結構——線性表

文章目錄 線性表的定義和基本操作順序表線性表的鏈式表示 線性表的定義和基本操作 線性表是具有相同數據類型的(n≥0)個數據元素的有限序列&#xff0c;其中n為表長&#xff0c;當n0時線性表是一個空表。若用L命名線性表&#xff0c;則其中一般表示為&#xff1a;L(a1,a2,a3, …

.NET實現解析字符串表達式

一、引子功能需求 我們創建了一個 School 對象&#xff0c;其中包含了教師列表和學生列表。現在&#xff0c;我們需要計算教師平均年齡和學生平均年齡。 //創建對象 School school new School() {Name "小菜學園",Teachers new List<Teacher>(){new Teach…

CCLINK轉MODBUS-TCP網關cclink通訊接線圖 終端電阻

大家好&#xff0c;今天我們要聊的是生產管理系統中的CCLINK和MODBUS-TCP協議&#xff0c;它們的不同使得數據互通比較困難&#xff0c;但捷米JM-CCLK-TCP網關的出現改變了這一切。 1捷米JM-CCLK-TCP是一款自主研發的CCLINK從站功能的通訊網關&#xff0c;它的主要功能是將各種…

后端開發5.Redis的搭建

使用docker安裝 Redis【redis】(6379) 拉取Redis鏡像 docker pull redis:6.2.6 啟動Redis容器 docker run -di --name=redis -p 6379:6379 redis:6.2.6 啟動Redis容器并設置密碼 docker run -di --name=redis -p 6379:6379 redis:6.2.6 --requirepass "密碼" 測…

D455+VINS-Fusion+surfelmapping 稠密建圖(三)

繼續&#xff0c;由surfelmapping建立的點云生成octomap八叉樹柵格地圖 一、安裝OctomapServer 建圖包 安裝插件 sudo apt-get install ros-melodic-octomap-ros sudo apt-get install ros-melodic-octomap-msgs sudo apt-get install ros-melodic-octomap-server sudo apt-…

cubemx hal stm32 舵機 可減速 任意位置停止 驅動代碼

CubeMX配置 對于 STM32 F407VE 這里的84是來自APB1那路2倍頻得到&#xff1a; 代碼部分 兩個舵機都是180度的 servo.c #include "servo.h" #include "tim.h" #include "stdio.h"__IO uint32_t g_SteerUWT[2] {0}; uint16_t g_SteerDeg[…

React Native Maps的使用

介紹 React Native Maps是一個用于在React Native應用中顯示地圖的庫。它提供了許多功能&#xff0c;如顯示地圖、標記位置、繪制多邊形等。以下是React Native Maps的使用步驟&#xff1a; 使用 首先&#xff0c;你需要在你的React Native項目中安裝React Native Maps庫。可…

青大數據結構【2014】

一、單選 二、簡答 為了解決順序隊列的假溢出問題&#xff0c;提出了循環隊列&#xff0c;即把存儲隊列的表從邏輯上看成一個環 判別隊列空和滿有三種方法&#xff1a; 1&#xff09;采用計數器判別&#xff0c;空時&#xff0c;計數器為0&#xff1b;滿時&#xff0c;計數器…