溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

c語言中數(shù)據(jù)存儲與原碼、反碼、補碼的示例分析

發(fā)布時間:2022-02-14 10:02:23 來源:億速云 閱讀:148 作者:小新 欄目:開發(fā)技術(shù)

這篇文章主要介紹了c語言中數(shù)據(jù)存儲與原碼、反碼、補碼的示例分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

1.數(shù)據(jù)的類型介紹

在學(xué)習(xí)數(shù)據(jù)儲存之前,讓我們先認識一下數(shù)據(jù)類型。以下這些數(shù)據(jù)類型是我們初學(xué)c語言時的基礎(chǔ)類型以及大小所占字節(jié)數(shù)。

比如所占字節(jié)數(shù)類型
char1//符數(shù)據(jù)的類型
shot2//短整型
int4//整形
long (規(guī)定sizeof(long)>=sizeof(int) )4//長整型
long long(部分編譯器不支持)8//更長的起整數(shù)
float4//單精度浮點數(shù)
double8//雙精度浮點數(shù)

還有構(gòu)造類型:

數(shù)組類型

結(jié)構(gòu)體類型struct

枚舉類型enum

聯(lián)合類型union

指針類型:

int* pa;

char* pb;

float* pc;

void* pd;

除了以上類型,實際上還有布爾類型:_Bool(專門用來表示真假的類型)

舉個栗子(在c99中可用)

#include<stdio.h>
#include<stdbool>
main()
{
_bool flag=true;
if(flat)
printf("hello world")
return 0;
}              //結(jié)果就會打印一個hello world

1.1整形家族

整形家族中包括int short long,還有char。

char也是整形家族中的嗎?

答案是:是的,因為char對應(yīng)的字符的ascii碼值中,字符對應(yīng)的就是整形。

在這些整形類型之中,還可以分為無符號整形和有符號整型:

int=signed int

short=signed short

long=signed long

那是否char 等于 signed char呢

結(jié)果又跟其他整形家族中的成員不同,在標準情況下char不是等于sign char~(但是在常規(guī)編譯器中是相等的)。

2.整形在數(shù)據(jù)內(nèi)存中的存儲

我們知道變量創(chuàng)建就是開辟空間,開辟空間的大小由數(shù)據(jù)的類型來決定。

那么數(shù)據(jù)在所在的空間是怎樣儲存的呢?

在vs2019中輸入:

int    a=20;
int    b=-10;

就代表在內(nèi)存中開辟四個字節(jié)的空間

c語言中數(shù)據(jù)存儲與原碼、反碼、補碼的示例分析

 其中14 00 00 00 就是a十六進制對應(yīng)反碼的值

c語言中數(shù)據(jù)存儲與原碼、反碼、補碼的示例分析

和前面相同,f6 ff ff ff就是b十六進制對應(yīng)反碼的值

我們都知道計算機都是以二進制來存儲信息,那為什么在內(nèi)存圖中看到的是十六進制呢?

這僅僅是便于觀察,當以十六進制儲存時,有沒有感到反碼有點長呢,如果換成二進制就更不宜觀察了,故規(guī)定以十六進制來保存。

提到這里,什么是反碼呢?為什么又反碼的出現(xiàn)呢?

2.1 原碼 反碼和補碼(三種整型數(shù)的表示方法)

原碼:原碼就是數(shù)字對應(yīng)二進制的表示方法,其中最后一位數(shù)字是符號位,表示正負的,

而小字節(jié)序就是二進制對應(yīng)的是數(shù)。

如a的原碼是:0000 0000 0000 0000 0000 1010 

反碼:反碼的數(shù)值就是在原碼的基礎(chǔ)之上進行轉(zhuǎn)換過來的,當數(shù)值為正數(shù)時,反碼的數(shù)據(jù)大小跟原碼相同,當數(shù)值是負數(shù)是,其反碼的值就是在原碼的基礎(chǔ)上,除了符號位,其他位都是按位取反。

補碼:補碼數(shù)值為正數(shù)時,其值大小就是原碼,為負時,其值的大小就是在反碼的基礎(chǔ)之上,在進行加一。

原碼得到補碼取反加一即可,其實補碼得到原碼也是取反加一(感興趣的可以試試)

舉個栗子:

a的原碼 反碼 補碼

原:0000 0000 0000 0000 0001 0100 

反:0000 0000 0000 0000 0001 0100 

補:0000 0000 0000 0000 0001 0100 

b的原碼 反碼 補碼

原:1000 0000 0000 0000 0000 1010

反:1111 1111   1111  1111  1111  0101

補:1111 1111  1111   1111   1111  0110

那我們系統(tǒng)會出現(xiàn)原碼反碼和補碼三種表示方法呢,一種表示方法不行嗎?

我們能想到的,科學(xué)家也能想到,但一種表示方法有缺陷。

就比如說:當計算1+(-1)的時候(計算機只能實現(xiàn)加法的運算)

統(tǒng)一用原碼的結(jié)果是

0000 0000 0000 0000  0000 0001

1000 0000 0000 0000 0000  0001

結(jié)果是1000 0000 0000 0000 0000  0010

用補碼計算的結(jié)果是:

0000 0000 0000 0000 0000  0001

0111  1111  1111 1111  1111  1111

結(jié)果是1000 0000 0000 0000 0000 0000 也就是0

你是不是瞬間知道為什么要三種表示方法,為什么有補碼的存在了

有沒有g(shù)et到科學(xué)家的偉大之處

2.2大小端字節(jié)序序的介紹

大小端字節(jié)序分別是哪一種?

c語言中數(shù)據(jù)存儲與原碼、反碼、補碼的示例分析

a在內(nèi)存中的數(shù)值44 33 22 11就是小端字節(jié)序

那大端字節(jié)序就是11 22 33 44

大小端字節(jié)序的定義是什么?

大端字節(jié)序:當一個數(shù)的低字節(jié)序放在高地址處,或者高字節(jié)序的放在低地址處時,就是我們所說的大端字節(jié)序。

小端字節(jié)序:當一個數(shù)的高字節(jié)序放在低地址處,或者低字節(jié)序的放在高地址處時,就是我們所說的小端字節(jié)序。

放在倒著就是小端字節(jié)序,記住它即可。

為什么數(shù)據(jù)要分大小端字節(jié)序呢?

大小端字節(jié)序來源于于喬納森&middot;斯威夫特的小說《格列佛游記》,這是因為在計算機系統(tǒng)中,我們都是以字節(jié)為單位的,每個地址單元都對應(yīng)著一個字節(jié),一個字節(jié)為8bit,但是在c語言中除了8bit的char之外,還有16bit的short型,32bit的long型(看具體編譯器),另外,對于位數(shù)大于8位的處理器,例外16位的或者32位的處理器,由于寄存器寬度大于一個字節(jié),那么必然存在著一個如何將多個字節(jié)序排序的問題。因此就導(dǎo)致了大端存儲模式,和小端存儲模式。

c語言中數(shù)據(jù)存儲與原碼、反碼、補碼的示例分析

 那么怎么判斷大小端字節(jié)序呢?

下面由一個例題來講解:(這是百度2015年系統(tǒng)工程師的筆試題)

用代碼來判斷系統(tǒng)大小端字節(jié)序:

int a;
 
char*pa=(char*)&a;
 
if(*pa==1)
 
printf("小端字節(jié)序“);
 
else
 
printf(“大端字節(jié)序”);

2.3 練習(xí)

題一:

//輸出結(jié)果是什么
#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
}

輸出的結(jié)果分別是-1 -1 255

前面兩個很容易理解 signed char與char意思都是有符號的整數(shù),所以打印的結(jié)果都是-1.

都是對于無符號來說這時候就要進行整形提升了

當char型以整形來打印時過程如下:

原碼:10000001

反碼:11111110

補碼:11111111

unsigned整形提升后:0000 0000 0000 0000 1111 1111

這是的補碼同樣也是: 0000 0000 0000 0000 1111 1111

就是最終c的值。

題二:

#include<stdio.h>
 
int main()
{
char a=-128;
printf(%u\n",a);  //u就是以無符號的類型打印出來
return 0;
}

-128的原碼: 1000 0000 0000 0000 1000 0000

反碼1111 1111 1111 1111 0111 1111

補碼1111  1111 1111 1111 1000 0000

因為是char型 補碼提取后:10000000

正進行整形提升,因為char是無符號整形,所以提升后:

1111 1111 1111 1111 1000 0000

再以無符號整形形式打印后原反補相同即:1111 1111 1111 1111 1000 0000

再轉(zhuǎn)化成十進制:4294967169

運行證明以如下

c語言中數(shù)據(jù)存儲與原碼、反碼、補碼的示例分析

數(shù)據(jù)的范圍是多少呢?unsigned char與char存放的數(shù)據(jù)是否相等呢?

事實證明char與unsigned char數(shù)據(jù)范圍并不一樣

char的整形數(shù)據(jù)范圍是-128~127,而unsigned char的范圍是0~255;

(short 與unsigned short的整形取值范圍也不一樣

short的整形數(shù)據(jù)范圍是-32768~32767,而unsigned short能存儲的數(shù)據(jù)范圍則是0~65535

3.浮點型在內(nèi)存中的存儲

首先列出一個常見浮點數(shù)表示方法:

1E10 可能你并不知道這是什么意思;

實際上他的意思是1.0*10^10;

3.1 先舉一個例子

#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;
}

n的值為:9

*pFloat的值為:0.00

num的值為:1091567616

*pFloat的值為:9.000000

  這個結(jié)果是否跟你想的一樣呢?

 其實n的值與最后一個*pFloat的值可能我們很容易知道(也可能是猜的 哈哈)

在求解這道題之前讓我們先了解這個題的知識吧~

3.2 浮點數(shù)儲存的規(guī)則

IEEE(電氣和電子工程協(xié)會754標準)標準規(guī)定:

任何二進制的浮點數(shù)都可以以這種標準表示出來:

基本公式是:(-1)^S*M*2^E;(這里的E是無符號類型)

其中M是有效數(shù)子,E是指數(shù),S用來表示正負;

舉個栗子:

5.5&mdash;&mdash;10進制的表示

轉(zhuǎn)化為二進制的結(jié)果是:101.1;

用公式表示為:(-1)^0 (1.011)*2^2    此時S=0,M=1.011,E=2;

c語言中數(shù)據(jù)存儲與原碼、反碼、補碼的示例分析

 對于64位浮點數(shù),最高位1位是符號位s,接著是11位是指數(shù)E, 剩下的52位是有效數(shù)字。

c語言中數(shù)據(jù)存儲與原碼、反碼、補碼的示例分析

如果E為八位,他的取值范圍0~255,如果E為11為,他的取值范圍0~2047;

有兩個極限 

當E為0時,此時的真實的E為1-127=-126;此時的數(shù)值根據(jù)公式,也就是無限接近與0;

當E為254時,此時的真實的E為254-127=127;此時的數(shù)值根據(jù)公式,也就是無窮大。

說到這里,你可能有一點疑惑,為什么都要減一個127,這是因為避免出現(xiàn)E為負數(shù)的情況(因為這里的E是無符號整形),在真實的E的基礎(chǔ)上加了127,所以為了得到求出真實的E,就需要減去一個127.

c語言中數(shù)據(jù)存儲與原碼、反碼、補碼的示例分析

 現(xiàn)在回到原來的題目之上

0000 0000 0000 0000 0000 0000 0000 1001--九的原碼反碼與補碼。

這里的0 是 s;00000000為E;0000000000000000001001為m

此時(-1)^0*0.00000001*10*2^(-126)

由于float默認只打印小數(shù)點后六位,所以最終打印0.000000;

九的轉(zhuǎn)化位二進制:1.001;

1.001*2^3

=0 M=1.001 E=3;

0100 0001 0001 0000 0000 0000 0000 0000

再以整形的形式打印的話,此時的值就是0100 0001 0001 0000 0000 0000 0000 0000就是num的補碼,由于符號位是0,所以最終的原碼等于補碼。也就是1091567616

如果以浮點型打印的話也就是9.000000

感謝你能夠認真閱讀完這篇文章,希望小編分享的“c語言中數(shù)據(jù)存儲與原碼、反碼、補碼的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI