C語(yǔ)言之整數(shù)存儲(chǔ)底層邏輯用法解讀
一、原碼 反碼 補(bǔ)碼
1.原碼
二進(jìn)制表示法。最高位為符號(hào)位,表示正負(fù);剩下位為數(shù)值位,表示數(shù)值大小。
例如(以8位舉例):
- 10的原碼:00001010
- -10的原碼:10001010
2.反碼
符號(hào)位不變,其余位取反。
例如(以8位舉例):
- 10的反碼:00001010
- -10的反碼:11110101
正數(shù)的反碼=原碼
3.補(bǔ)碼
反碼+1。
例如(以8位舉例):
- 10的補(bǔ)碼:00001010
- -10的補(bǔ)碼:11110110
正數(shù):原碼、反碼、補(bǔ)碼都相等
負(fù)數(shù):
原碼 -> 補(bǔ)碼:符號(hào)位不變,其余位取反;+1
補(bǔ)碼 -> 原碼:
方法一:-1;符號(hào)位不變,其余位取反
方法二:符號(hào)位不變,其余位取反;+1
二、整數(shù)存儲(chǔ)
1.計(jì)算機(jī)中的原反補(bǔ)規(guī)則
所有的整型數(shù)據(jù)在計(jì)算機(jī)中都已補(bǔ)碼的形式存儲(chǔ)和運(yùn)算。
計(jì)算機(jī)在處理整型數(shù)據(jù)時(shí),會(huì)先將其看作int類型進(jìn)行處理;若超出int類型的范圍,則將其看作long long型進(jìn)行處理。
例如:
char a = -10;
計(jì)算機(jī)首先申請(qǐng)了1個(gè)字節(jié)的空間,并將這篇空間命名為a;-10的補(bǔ)碼為11111111 11111111 11111111 11110110,將這個(gè)補(bǔ)碼存入a這片空間,因?yàn)閍只有1個(gè)字節(jié),所以只能存入最后一個(gè)字節(jié),即11110110。
char b = 10;
計(jì)算機(jī)首先申請(qǐng)了1個(gè)字節(jié)的空間,并將這篇空間命名為b;10的補(bǔ)碼為00000000 00000000 00000000 00001010,將這個(gè)補(bǔ)碼存入a這片空間,因?yàn)閍只有1個(gè)字節(jié),所以只能存入最后一個(gè)字節(jié),即00001010。
2.有符號(hào)/無(wú)符號(hào)整數(shù)類型
在計(jì)算機(jī)中,char/short/int/long/long long屬于有符號(hào)(signed)的整數(shù)類型,此外,計(jì)算機(jī)中還提供了一種無(wú)符號(hào)(unsigned)的整數(shù)類型。
| 類型 | 格式控制符 | 比特位使用規(guī)則 | 大小(Byte) | 范圍 | 特殊值 |
| 有符號(hào)(signed可寫可不寫)的整數(shù)家族 | |||||
| char | %hhd/%c | 1位符號(hào)位 7位數(shù)值位 | 1Byte | -2^7~2^7-1 | 10000000(-2^7) |
| short | %hd | 1位符號(hào)位 15位數(shù)值位 | 2Byte | -2^15~2^15-1 | 10000000 00000000(-2^15) |
| int | %d | 1位符號(hào)位 31位數(shù)值位 | 4Byte | -2^31~2^31-1 | 10000000 00000000 00000000 00000000(-2^31) |
| long | %ld | 1位符號(hào)位 31位數(shù)值位 | 4Byte | -2^31~2^31-1 | 10000000 00000000 00000000 00000000 (-2^31) |
| long long | %lld | 1位符號(hào)位 63位數(shù)值位 | 8Byte | -2^63~2^63-1 | 10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000(-2^63) |
| 無(wú)符號(hào)(unsigned)的整數(shù)家族 | |||||
| unsigned char | %hhu | 8位數(shù)值位 | 1Byte | 0~2^8 | |
| unsigned short | %hu | 16位數(shù)值位 | 2Byte | 0~2^16 | |
| unsigned int | %u | 32位數(shù)值位 | 4Byte | 0~2^32 | |
| unsigned long | %lu | 32位數(shù)值位 | 4Byte | 0~2^64 | |
| unsigned long long | %llu | 64位數(shù)值位 | 8Byte | 0~2^64 | |
以char為例:
| char(1位符號(hào)位 7位數(shù)值位) | 數(shù)值 | unsigned char(8位數(shù)值位) | 數(shù)值 | |
| 0 1111111 | 127 | 01111111 | 127 | |
| 0 1111110 | 126 | 01111110 | 126 | |
| ...... | ...... | |||
| 0 0000001 | 1 | 00000001 | 1 | |
| 0 0000000 | 0 | 00000000 | 0 | |
| 1 0000000 | -128 | 10000000 | 128 | |
| 1 0000001 | -1 | 10000001 | 129 | |
| 1 0000010 | -2 | 10000010 | 130 | |
| ...... | ...... | |||
| 1 1111110 | -126 | 1 1111110 | 254 | |
| 1 1111111 | -127 | 11111111 | 255 | |
| char | 1個(gè)符號(hào)位+7個(gè)數(shù)值位 | 最大值 127(0 1111111) | 最小值 -128(1 1111111) |
| unsigned char | 8個(gè)數(shù)值位 | 最大值 255(11111111) | 最小值 0(00000000) |
- 因?yàn)?strong>char類型中10000000沒有別的數(shù)可以表示,計(jì)算機(jī)強(qiáng)制規(guī)定它為最小值-2^7(-128)。
- 同理,short類型中,計(jì)算機(jī)強(qiáng)制規(guī)定10000000 00000000為最小值-2^15;
- int和long類型中,計(jì)算機(jī)強(qiáng)制規(guī)定10000000 00000000 00000000 00000000為最小值-2^31;
- long long類型中,計(jì)算機(jī)強(qiáng)制規(guī)定10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000為最小值-2^63;
3.相同字節(jié)大小轉(zhuǎn)換
int main() {
//-10的原碼:10000000 00000000 00000000 00001010
//-10的反碼:11111111 11111111 11111111 11110101
//-10的補(bǔ)碼:11111111 11111111 11111111 11110110
char a = -10; //只有一個(gè)字節(jié)的空間,只能存放下最后一個(gè)字節(jié):11110110
unsigned char b = -10; //只有一個(gè)字節(jié)的空間,只能存放下最后一個(gè)字節(jié):11110110
printf("a=%hhd,b=%hhd\n", a, b);
/*
a:11110110
1.按照%hhd(有符號(hào)char類型)的格式輸出,所以要將11110110看作是1個(gè)符號(hào)位+7個(gè)數(shù)值位
2.將補(bǔ)碼轉(zhuǎn)換成原碼:11110110->10001010
(符號(hào)位是1,為負(fù)數(shù);負(fù)數(shù)的原碼=補(bǔ)碼-1,再符號(hào)位不變,其余位取反)
3.將原碼轉(zhuǎn)換成十進(jìn)制:10001010->-10
b:11110110
1.按照%hhd(有符號(hào)char類型)的格式輸出,所以要將11110110看作是1個(gè)符號(hào)位+7個(gè)數(shù)值位
2.將補(bǔ)碼轉(zhuǎn)換成原碼:11110110->10001010
(符號(hào)位是1,為負(fù)數(shù);負(fù)數(shù)的原碼=補(bǔ)碼-1,再符號(hào)位不變,其余位取反)
3.將原碼轉(zhuǎn)換成十進(jìn)制:10001010->-10
*/
printf("a=%hhu,b=%hhu\n", a, b);
/*
a:11110110
1.按照%hhu(無(wú)符號(hào)char類型)的格式輸出,所以要將11110110看作是8個(gè)數(shù)值位
2.將補(bǔ)碼轉(zhuǎn)換成原碼:11110110->10001010(正數(shù)的原碼、反碼、補(bǔ)碼相同)
3.將原碼轉(zhuǎn)換成十進(jìn)制:10001010->138
b:11110110
1.按照%hhu(無(wú)符號(hào)char類型)的格式輸出,所以要將11110110看作是8個(gè)數(shù)值位
2.將補(bǔ)碼轉(zhuǎn)換成原碼:11110110->10001010(正數(shù)的原碼、反碼、補(bǔ)碼相同)
3.將原碼轉(zhuǎn)換成十進(jìn)制:10001010->138
*/
return 0;
}4.不同字節(jié)大小轉(zhuǎn)換
(1)小字節(jié)轉(zhuǎn)大字節(jié)
符號(hào)位不變,數(shù)值位不變,其余位補(bǔ)符號(hào)位的數(shù)字。
int main() {
//-10的原碼:10000000 00000000 00000000 00001010
//-10的反碼:11111111 11111111 11111111 11110101
//-10的補(bǔ)碼:11111111 11111111 11111111 11110110
char a = -10; //只有一個(gè)字節(jié)的空間,只能存放下最后一個(gè)字節(jié):11110110
unsigned char b = -10; //只有一個(gè)字節(jié)的空間,只能存放下最后一個(gè)字節(jié):11110110
printf("a=%hd,b=%hd\n", a, b);
/*
a:11110110 -> a的類型是有符號(hào)char類型,符號(hào)位:1
1.按照%hd(有符號(hào)short類型)的格式輸出,所以要先將11110110擴(kuò)充為2個(gè)字節(jié):
11110110->11111111 11110110
(符號(hào)位不變,數(shù)值位不變,其余位補(bǔ)符號(hào)位的數(shù)字,即補(bǔ)1)
2.將11111111 11110110看作是1個(gè)符號(hào)位+15個(gè)數(shù)值位
3.將補(bǔ)碼轉(zhuǎn)換成原碼:11111111 11110110->10000000 00001010
(符號(hào)位是1,為負(fù)數(shù);負(fù)數(shù)的原碼=補(bǔ)碼-1,再符號(hào)位不變,其余位取反)
4.將原碼轉(zhuǎn)換成十進(jìn)制:10000000 00001010->-10
b:11110110 -> b的類型是無(wú)符號(hào)char類型,符號(hào)位:0
1.按照%hd(有符號(hào)short類型)的格式輸出,所以要先將11110110擴(kuò)充為2個(gè)字節(jié):
11110110->00000000 11110110
(符號(hào)位不變,數(shù)值位不變,其余位補(bǔ)符號(hào)位的數(shù)字,即補(bǔ)1)
2.將00000000 11110110看作是1個(gè)符號(hào)位+15個(gè)數(shù)值位
3.將補(bǔ)碼轉(zhuǎn)換成原碼:00000000 11110110->00000000 11110110
(符號(hào)位是0,為正數(shù);正數(shù)的原碼、反碼、補(bǔ)碼相同)
4.將原碼轉(zhuǎn)換成十進(jìn)制:00000000 11110110->246
*/
printf("a=%hu,b=%hu\n", a, b);
/*
a:11110110 -> a的類型是有符號(hào)char類型,符號(hào)位:1
1.按照%hu(無(wú)符號(hào)short類型)的格式輸出,所以要先將11110110擴(kuò)充為2個(gè)字節(jié):
11110110->11111111 11110110
(符號(hào)位不變,數(shù)值位不變,其余位補(bǔ)符號(hào)位的數(shù)字,即補(bǔ)0)
2.將11111111 11110110看作是16個(gè)數(shù)值位
3.將補(bǔ)碼轉(zhuǎn)換成原碼:11111111 11110110->11111111 11110110
(正數(shù)的原碼、反碼、補(bǔ)碼相同)
4.將原碼轉(zhuǎn)換成十進(jìn)制:11111111 11110110->65526
b:11110110 -> b的類型是無(wú)符號(hào)char類型,符號(hào)位:0
1.按照%hd(有符號(hào)short類型)的格式輸出,所以要先將11110110擴(kuò)充為2個(gè)字節(jié):
11110110->00000000 11110110
(符號(hào)位不變,數(shù)值位不變,其余位補(bǔ)符號(hào)位的數(shù)字,即補(bǔ)0)
2.將00000000 11110110看作是16個(gè)數(shù)值位
3.將補(bǔ)碼轉(zhuǎn)換成原碼:00000000 11110110->00000000 11110110
(正數(shù)的原碼、反碼、補(bǔ)碼相同)
4.將原碼轉(zhuǎn)換成十進(jìn)制:00000000 11110110->246
*/
return 0;
}(2)大字節(jié)轉(zhuǎn)小字節(jié)
直接強(qiáng)行截取。
int main() {
//-10的原碼:10000000 00000000 00000000 00001010
//-10的反碼:11111111 11111111 11111111 11110101
//-10的補(bǔ)碼:11111111 11111111 11111111 11110110
short a = -10;
//只有兩個(gè)字節(jié)的空間,只能存放下最后兩個(gè)字節(jié):11111111 11110110
unsigned short b = -10;
//只有兩個(gè)字節(jié)的空間,只能存放下最后兩個(gè)字節(jié):11111111 11110110
printf("a=%hhd,b=%hhd\n", a, b);
/*
a:11111111 11110110
1.按照%hhd(有符號(hào)char類型)的格式輸出,所以要先將11111111 11110110截取為1個(gè)字節(jié):
11111111 11110110->11110110
2.將11110110看作是1個(gè)符號(hào)位+7個(gè)數(shù)值位
3.將補(bǔ)碼轉(zhuǎn)換成原碼:11110110->10001010
(符號(hào)位是1,為負(fù)數(shù);負(fù)數(shù)的原碼=補(bǔ)碼-1,再符號(hào)位不變,其余位取反)
4.將原碼轉(zhuǎn)換成十進(jìn)制:10001010->-10
b:11111111 11110110
1.按照%hhd(有符號(hào)char類型)的格式輸出,所以要先將11111111 11110110截取為1個(gè)字節(jié):
11111111 11110110->11110110
2.將11110110看作是1個(gè)符號(hào)位+7個(gè)數(shù)值位
3.將補(bǔ)碼轉(zhuǎn)換成原碼:11110110->10001010
(符號(hào)位是1,為負(fù)數(shù);負(fù)數(shù)的原碼=補(bǔ)碼-1,再符號(hào)位不變,其余位取反)
4.將原碼轉(zhuǎn)換成十進(jìn)制:10001010->-10
*/
printf("a=%hhu,b=%hhu\n", a, b);
/*
a:11110110
1.按照%hhu(無(wú)符號(hào)char類型)的格式輸出,所以要先將11111111 11110110截取為1個(gè)字節(jié):
11111111 11110110->11110110
2.將11110110看作是8個(gè)數(shù)值位
3.將補(bǔ)碼轉(zhuǎn)換成原碼:11110110->11110110
(正數(shù)的原碼、反碼、補(bǔ)碼相同)
4.將原碼轉(zhuǎn)換成十進(jìn)制:11110110->246
b:11110110
1.按照%hhu(無(wú)符號(hào)char類型)的格式輸出,所以要先將11111111 11110110截取為1個(gè)字節(jié):
11111111 11110110->11110110
2.將11110110看作是8個(gè)數(shù)值位
3.將補(bǔ)碼轉(zhuǎn)換成原碼:11110110->11110110
(正數(shù)的原碼、反碼、補(bǔ)碼相同)
4.將原碼轉(zhuǎn)換成十進(jìn)制:11110110->246
*/
return 0;
}總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
C語(yǔ)言容易被忽視的函數(shù)設(shè)計(jì)原則基礎(chǔ)
C語(yǔ)言的設(shè)計(jì)目標(biāo)是提供一種能以簡(jiǎn)易的方式編譯、處理低級(jí)存儲(chǔ)器、產(chǎn)生少量的機(jī)器碼以及不需要任何運(yùn)行環(huán)境支持便能運(yùn)行的編程語(yǔ)言.那么C語(yǔ)言函數(shù)設(shè)計(jì)的一般原則和技巧都是怎樣的呢,下面帶你了解2022-04-04
c++只保留float型的小數(shù)點(diǎn)后兩位問(wèn)題
這篇文章主要介紹了c++只保留float型的小數(shù)點(diǎn)后兩位問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11
c++項(xiàng)目中后綴名vcxproj和sln的區(qū)別及說(shuō)明
這篇文章主要介紹了c++項(xiàng)目中后綴名vcxproj和sln的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05
C語(yǔ)言實(shí)現(xiàn)宿舍管理課程設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)宿舍管理課程設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
C++11中std::function與std::bind的用法實(shí)例
大家都知道C++11中增加了許多的新特性,下面這篇文章主要給大家介紹了關(guān)于C++11中std::function與std::bind的用法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-05-05
C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易停車場(chǎng)管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易停車場(chǎng)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03

