当前位置:网站首页>數據的存儲(進階)
數據的存儲(進階)
2022-06-22 05:37:00 【頭發沒有代碼多】
目錄
數據類型介紹
char //字符數據類型short //短整型int //整形long //長整型long long //更長的整形float //單精度浮點數double //雙精度浮點數類型的意義:
1. 使用這個類型開辟內存空間的大小(大小决定了使用範圍)。2. 如何看待內存空間的視角
類型的基本歸類:
整形家族:
char //char'類型的本質是ASCII碼值,所以在整形裏面unsigned charsigned charshortunsigned short [int]signed short [int]intunsigned intsigned intlongunsigned long [int]signed long [int]
一般情况下int a,此時a是signed int類型,而char不一樣char a,a此時是signed char還是unsigned char這個C語言標准是未定義的,由編譯器决定char是signed還是unsigned
浮點型家族
floatdouble浮點型家族:只要是錶示小數就可以使用浮點型,flaot 的精度低,存儲的數值範圍較小,double的精度高,存儲的數據的範圍更大。
構造類型:
> 數組類型> 結構體類型 struct> 枚舉類型 enum> 聯合類型 union
指針類型
int *pi;char *pc;float* pf;void* pv;
空類型:
void 錶示空類型(無類型)通常應用於函數的返回類型、函數的參數、指針類型。

紅色框錶示函數不需要返回值,藍色框錶示函數不需要參數,但如果我們硬給函數傳參,函數會正常運行,只不過是沒有接收參數罷了 ,倆個void其實都課省略,但最好不要進行省略
整形在內存中的存儲
int a = 20;int b = -10;我們知道為 a 分配四個字節的空間。 那如何存儲? 下來了解下面的概念:
原碼、反碼、補碼
計算機中的整數有三種2進制錶示方法,即原碼、反碼和補碼。三種錶示方法均有符號比特和數值比特兩部分,符號比特都是用0錶示“正”,用1錶示“負”,而數值比特正數的原、反、補碼都相同。負整數的三種錶示方法各不相同。
原碼
直接將數值按照正負數的形式翻譯成二進制就可以得到原碼。
反碼
將原碼的符號比特不變,其他比特依次按比特取反就可以得到反碼。
補碼
反碼+1就得到補碼。 在計算機中整形數據以補碼的形式進行存儲
前面的博客有涉及到原碼反碼補碼的一些知識和二進制下的計算
在計算機系統中,數值一律用補碼來錶示和存儲。原因在於,使用補碼,可以將符號比特和數值域統一處理;同時,加法和减法也可以統一處理(CPU只有加法器)此外,補碼與原碼相互轉換,其運算過程是相同的,不需要額外的硬件電路。
原反補轉換法則
方法一
一、正整數的原碼、反碼、補碼完全一樣,即符號比特固定為0,數值比特相同
二、負整數的符號比特固定為1,由原碼變為補碼時,規則如下:
1、原碼符號比特1不變,整數的每一比特二進制數比特求反,得到反碼
2、反碼符號比特1不變,反碼數值比特最低比特加1,得到補碼
補碼得原碼:補碼-1得反碼,反碼符號比特不變其餘比特取反得原碼
方法二
一、正整數的原碼、反碼、補碼完全一樣,即符號比特固定為0,數值比特相同
補碼得原碼:補碼符號比特不變其餘比特按比特取反,取反之後得結果+1得到原碼
-1和1以補碼的形式進行相加, 加完之後為33比特,多出一比特。然後去掉最高比特就得到最終結果的補碼

大小端介紹
什麼大端小端:
大端(存儲)模式,是指數據的低比特保存在內存的高地址中,而數據的高比特,保存在內存的低地址中;小端(存儲)模式,是指數據的低比特保存在內存的低地址中,而數據的高比特,,保存在內存的高地址中。

我們在編譯器中運行可發現數據是反著存的,為什麼要倒著放呢?
這裏如11 22 33 44,其實這些數據在內存中是可以隨便放的,但是使用的時候必須得原樣拿出,如數據本來是11 22 33 44,存放形式 33 22 11 44,但是使用的時候必須按11 22 33 44使用,即拿出來的時候必須得恢複原樣,但是亂序存儲過於麻煩,一般選擇正序存儲或倒序存儲
我們把這倆中方式分別稱為大端字節序存儲和小端字節序存儲
大端字節序存儲:
把一個數據的高比特字節序的內容存放在低地址處,把低比特字節序的內容放在高地址處,就是大端字節序存儲。
小端字節序存儲:
把一個數據的低比特字節序的內容存放在低地址處,把高比特字節序的內容放在高地址處,就是小端字節序存儲。
一個字節看不出大小端的順序
為什麼有大端和小端:
為什麼會有大小端模式之分呢?這是因為在計算機系統中,我們是以字節為單比特的,每個地址單元 都對應著一個字節,一個字節為8 bit。但是在C語言中除了8 bit的char之外,還有16 bit的short 型,32 bit的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 check(int a)
{
return *(char*)&a;
}
int main()
{
int a = 1;
check(a);
if (check)
printf("小端存儲\n");
else
printf("大端存儲\n");
return 0;
}

練習題
#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取值範圍-128-127,
其它數字均可按照原碼,反碼,補碼轉換規則,算出來,但是10000000不能這樣算,直接人為是-128
unsigned char的取值範圍是0-255,應為無符號數沒有負數


short類型占倆個字節,也就是16個二進制數字,取值範圍在下面


這裏的C為什麼是255?看下面圖解


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

習題3
#include <stdio.h> int main() { char a = 128; printf("%u\n", a); printf("%d\n", a); return 0; }
這個跟前面的題一樣都是先發生截斷,然後整形提昇,然後再打印
習題4
#include <stdio.h>
int main()
{
int i = -20;
unsigned int j = 10;
printf("%d\n", i + j);
return 0;
}
習題5 unsigned三碼習題
#include<stdio.h> int main() { unsigned int i; for (i = 9; i >= 0; i--) { printf("%u\n", i); } return 0; }

我們看到這裏9-0都是正常打印但是到-1就出現了問題,具體原因請看下圖


二進制下的32個1,換成十進制為一個特別大的數字,所以會打印4294967295,之後每次i--這個數都會减一
習題6 signed char取值範圍問題
#include<stdio.h> #include<string.h> int main() { char a[1000]; int i; for (i = 0; i < 1000; i++) { a[i] = -1 - i; } printf("%d", strlen(a)); return 0; }
這裏把數字放入到數組a中,而a是char類型,範圍為-128~127
這裏是-1-i,其實就是上面這個圖逆序的走法,從-1~-128~127~0
\0的ASCII碼值是0,strlen遇到\0會停下來,所以在遇到0之前,數組裏面已經存了128+127個數字了,所以打印255
習題7 無符號char取值範圍習題
#include<stdio.h> unsigned char i = 0; int main() { for (i = 0; i <= 255; i++) { printf("hello world\n"); } return 0; }
程序運行後會進入死循環,這是因為i是unsigned char類型範圍是0~255,前面有說過,i為255之後,i+1,此時i又變為0,陷入死循環
習題8 關於strlen返回值類型的習題
#include<stdio.h> #include<string.h> int main() { if (strlen("abc") - strlen("abcdef") >= 0) printf(">"); else printf("<"); return 0; }
這裏會打印>是因為strlen返回值為unsigned int類型,無論怎樣運算結果都>=0.
浮點型在內存中的存儲
浮點數家族包括: float、double、long double 類型。浮點數錶示的範圍:float.h中定義用everything查找float.h然後用VS打開,就可看到浮點數的範圍,整形輸入litmits.h可查看範圍
浮點數存儲規則
根據國際標准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。9.5f9.5f其實用二進制錶示為:1001.1,這跟權重有關系,因為2^-1為0.5
1001.1=1.0011*2^3
S=0,M=1.0011,e=3
例:9.6f
二進制:1001.XXXXXX,因為這個0.6不好錶示,需要一堆0和1,但是如果數字過多就有可能存不下,因此浮點數就產生了精度問題
float 4byte double 8byte
浮點數如何保存
IEEE 754規定:對於32比特的浮點數,最高的1比特是符號比特s,接著的8比特是指數E,剩下的23比特為有效數字M。
對於64比特的浮點數,最高的1比特是符號比特S,接著的11比特是指數E,剩下的52比特為有效數字M。
特別規定:
前面說過, 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。如0.5=1.0*2^-1 M=1.0,E=-1,S=0E為負數不在範圍之內,所以 IEEE 754規定,存入內存時E的真實值必須再加上一個中間數:對於8比特的E(float),這個中間數是127。對於11比特的E(double),這個中間數是1023。剛才E=-1,按float類型,E+127=126,把126存放到E所在的空間當中(8個bit)
結果一致,為小端存儲
浮點數如何往出拿
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);
浮點數列題
#include<stdio.h> 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; }
所以會打印0.0000000000
边栏推荐
- 亚马逊和独立站,不是简单的二选一
- Working method: 3C scheme design method
- 在线文本代码对比工具
- Research Report on demand and investment opportunities in key areas of global and Chinese strontium tungstate industry 2022-2027
- ActiveMQ knowledge summary of Message Oriented Middleware
- postmanUtils工具类,模拟postman的get,post请求
- 《双内核实时系统下各个进程间通信方法的性能分析和测试》
- [issue 26] 123hr experience of Tencent teg+ operation development
- How can enterprises implement ERP projects automatically?
- Summary of knapsack problem
猜你喜欢
![P1077 [noip2012 popularization group] flower display](/img/0d/f74a2036aa261ed327d9d74291aacc.png)
P1077 [noip2012 popularization group] flower display

记本地项目启动报错:无效的源发行版: 8

《MATLAB 神经网络43个案例分析》:第29章 极限学习机在回归拟合及分类问题中的应用研究——对比实验
![[graduation season · advanced technology Er] a graduate student's chatter](/img/c2/dc77b8ffecfcb0a495e1dc8b6e7922.png)
[graduation season · advanced technology Er] a graduate student's chatter

Analysis of 43 cases of MATLAB neural network: Chapter 29 research on the application of limit learning machine in regression fitting and classification -- Comparative Experiment

Learning method 3 for promotion of large enterprises: chain learning method

《MATLAB 神经网络43个案例分析》:第28章 决策树分类器的应用研究——乳腺癌诊断

YARN 应用提交过程

我不建议你工作太拼命

独立站优化清单丨如何有效提升站内转化率?
随机推荐
搜狗输入法无法输出中文
【云原生】2.2 kubeadm创建集群
Rambbmitmq consumer
[issue 26] 123hr experience of Tencent teg+ operation development
独立站 “ 去中心化 ” 模式崛起,席卷跨境企业转型浪潮
2022 Shenzhen Futian District specialized special new small giant enterprise application conditions, with a subsidy of 500000 yuan
关于二分一些模板
SQL classification, user properties
移动端 realm数据库使用及解耦,跨线程安全使用 OC realm
Traveler's budget (Los Angeles Valley)
毕业季 | 新的开始,不说再见
P1160 queue arrangement
毕业季 | 新的开始,不说再见
nacos server 源码运行实现
Facing the bonus period of Google traffic, how do independent station sellers take advantage of the situation to market?
Rétroaction sur la remise des diplômes! Tous les contributeurs de la communauté Apache Doris sont ici pour recevoir des cadeaux!
我不建议你工作太拼命
OPTEE notes
Privatized lightweight continuous integration deployment scheme --05- continuous deployment service -drone (Part 1)
Facebook账户 “ 解封、防封、养号 ” 知识要点,已收藏!
我們在編譯器中運行可發現數據是反著存的,為什麼要倒著放呢?

















