您好,登錄后才能下訂單哦!
這篇文章主要介紹了c語言中數據存儲與原碼、反碼、補碼的示例分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
在學習數據儲存之前,讓我們先認識一下數據類型。以下這些數據類型是我們初學c語言時的基礎類型以及大小所占字節數。
比如 | 所占字節數 | 類型 |
char | 1 | //符數據的類型 |
shot | 2 | //短整型 |
int | 4 | //整形 |
long (規定sizeof(long)>=sizeof(int) ) | 4 | //長整型 |
long long(部分編譯器不支持) | 8 | //更長的起整數 |
float | 4 | //單精度浮點數 |
double | 8 | //雙精度浮點數 |
還有構造類型:
數組類型
結構體類型struct
枚舉類型enum
聯合類型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; } //結果就會打印一個hello world
整形家族中包括int short long,還有char。
char也是整形家族中的嗎?
答案是:是的,因為char對應的字符的ascii碼值中,字符對應的就是整形。
在這些整形類型之中,還可以分為無符號整形和有符號整型:
int=signed int
short=signed short
long=signed long
那是否char 等于 signed char呢
結果又跟其他整形家族中的成員不同,在標準情況下char不是等于sign char~(但是在常規編譯器中是相等的)。
我們知道變量創建就是開辟空間,開辟空間的大小由數據的類型來決定。
那么數據在所在的空間是怎樣儲存的呢?
在vs2019中輸入:
int a=20; int b=-10;
就代表在內存中開辟四個字節的空間
其中14 00 00 00 就是a十六進制對應反碼的值
和前面相同,f6 ff ff ff就是b十六進制對應反碼的值
我們都知道計算機都是以二進制來存儲信息,那為什么在內存圖中看到的是十六進制呢?
這僅僅是便于觀察,當以十六進制儲存時,有沒有感到反碼有點長呢,如果換成二進制就更不宜觀察了,故規定以十六進制來保存。
提到這里,什么是反碼呢?為什么又反碼的出現呢?
原碼:原碼就是數字對應二進制的表示方法,其中最后一位數字是符號位,表示正負的,
而小字節序就是二進制對應的是數。
如a的原碼是:0000 0000 0000 0000 0000 1010
反碼:反碼的數值就是在原碼的基礎之上進行轉換過來的,當數值為正數時,反碼的數據大小跟原碼相同,當數值是負數是,其反碼的值就是在原碼的基礎上,除了符號位,其他位都是按位取反。
補碼:補碼數值為正數時,其值大小就是原碼,為負時,其值的大小就是在反碼的基礎之上,在進行加一。
原碼得到補碼取反加一即可,其實補碼得到原碼也是取反加一(感興趣的可以試試)
舉個栗子:
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
那我們系統會出現原碼反碼和補碼三種表示方法呢,一種表示方法不行嗎?
我們能想到的,科學家也能想到,但一種表示方法有缺陷。
就比如說:當計算1+(-1)的時候(計算機只能實現加法的運算)
統一用原碼的結果是
0000 0000 0000 0000 0000 0001
1000 0000 0000 0000 0000 0001
結果是1000 0000 0000 0000 0000 0010
用補碼計算的結果是:
0000 0000 0000 0000 0000 0001
0111 1111 1111 1111 1111 1111
結果是1000 0000 0000 0000 0000 0000 也就是0
你是不是瞬間知道為什么要三種表示方法,為什么有補碼的存在了
有沒有get到科學家的偉大之處
大小端字節序分別是哪一種?
a在內存中的數值44 33 22 11就是小端字節序
那大端字節序就是11 22 33 44
大小端字節序的定義是什么?
大端字節序:當一個數的低字節序放在高地址處,或者高字節序的放在低地址處時,就是我們所說的大端字節序。
小端字節序:當一個數的高字節序放在低地址處,或者低字節序的放在高地址處時,就是我們所說的小端字節序。
放在倒著就是小端字節序,記住它即可。
為什么數據要分大小端字節序呢?
大小端字節序來源于于喬納森·斯威夫特的小說《格列佛游記》,這是因為在計算機系統中,我們都是以字節為單位的,每個地址單元都對應著一個字節,一個字節為8bit,但是在c語言中除了8bit的char之外,還有16bit的short型,32bit的long型(看具體編譯器),另外,對于位數大于8位的處理器,例外16位的或者32位的處理器,由于寄存器寬度大于一個字節,那么必然存在著一個如何將多個字節序排序的問題。因此就導致了大端存儲模式,和小端存儲模式。
那么怎么判斷大小端字節序呢?
下面由一個例題來講解:(這是百度2015年系統工程師的筆試題)
用代碼來判斷系統大小端字節序:
int a; char*pa=(char*)&a; if(*pa==1) printf("小端字節序“); else printf(“大端字節序”);
題一:
//輸出結果是什么 #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 }
輸出的結果分別是-1 -1 255
前面兩個很容易理解 signed char與char意思都是有符號的整數,所以打印的結果都是-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
再轉化成十進制:4294967169
運行證明以如下
數據的范圍是多少呢?unsigned char與char存放的數據是否相等呢?
事實證明char與unsigned char數據范圍并不一樣
char的整形數據范圍是-128~127,而unsigned char的范圍是0~255;
(short 與unsigned short的整形取值范圍也不一樣
short的整形數據范圍是-32768~32767,而unsigned short能存儲的數據范圍則是0~65535
首先列出一個常見浮點數表示方法:
1E10 可能你并不知道這是什么意思;
實際上他的意思是1.0*10^10;
#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
這個結果是否跟你想的一樣呢?
其實n的值與最后一個*pFloat的值可能我們很容易知道(也可能是猜的 哈哈)
在求解這道題之前讓我們先了解這個題的知識吧~
IEEE(電氣和電子工程協會754標準)標準規定:
任何二進制的浮點數都可以以這種標準表示出來:
基本公式是:(-1)^S*M*2^E;(這里的E是無符號類型)
其中M是有效數子,E是指數,S用來表示正負;
舉個栗子:
5.5——10進制的表示
轉化為二進制的結果是:101.1;
用公式表示為:(-1)^0 (1.011)*2^2 此時S=0,M=1.011,E=2;
對于64位浮點數,最高位1位是符號位s,接著是11位是指數E, 剩下的52位是有效數字。
如果E為八位,他的取值范圍0~255,如果E為11為,他的取值范圍0~2047;
有兩個極限
當E為0時,此時的真實的E為1-127=-126;此時的數值根據公式,也就是無限接近與0;
當E為254時,此時的真實的E為254-127=127;此時的數值根據公式,也就是無窮大。
說到這里,你可能有一點疑惑,為什么都要減一個127,這是因為避免出現E為負數的情況(因為這里的E是無符號整形),在真實的E的基礎上加了127,所以為了得到求出真實的E,就需要減去一個127.
現在回到原來的題目之上
0000 0000 0000 0000 0000 0000 0000 1001--九的原碼反碼與補碼。
這里的0 是 s;00000000為E;0000000000000000001001為m
此時(-1)^0*0.00000001*10*2^(-126)
由于float默認只打印小數點后六位,所以最終打印0.000000;
九的轉化位二進制: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語言中數據存儲與原碼、反碼、補碼的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。