C語(yǔ)言詳解關(guān)鍵字sizeof與unsigned及signed的用法
最冤枉的關(guān)鍵字sizeof理解
sizeof:確定一種類型在開(kāi)辟空間的時(shí)候的大小。
被誤解為函數(shù)
sizeof是關(guān)鍵字而不是函數(shù),可以借助編譯器來(lái)確定它的身份。
#include<stdio.h> int main() { int a = 10; printf("%d\n", sizeof(a)); printf("%d\n", sizeof(int)); printf("%d\n", sizeof a); printf("%d\n", sizeof int);//error return 0; }
sizeof(a)可以去掉()說(shuō)明sizeof不是函數(shù),是關(guān)鍵字(操作符),因?yàn)楹瘮?shù)后面的括號(hào)是不能省略的。
sizeof在計(jì)算變量所占的空間大小時(shí),可以省略括號(hào),而計(jì)算類型大小時(shí),不能省略括號(hào)。
注:sizeof操作符里面不能有其他運(yùn)算,否則達(dá)不到預(yù)期的結(jié)果。
sizeof(int)*p 表示什么意思
#include<stdio.h> int main() { int* p = NULL; int arr[10] = { 0 }; int* parr[3]; printf("%d\n", sizeof(p));//p是指針變量,指針變量的大小是固定的4或者8 printf("%d\n", sizeof(*p));//指針變量所指的變量所占的內(nèi)存的大小 printf("%d\n", sizeof(arr));//sizeof(arr)中arr指整個(gè)數(shù)組,即10個(gè)int類型元素。 printf("%d\n", sizeof(arr[10]));//數(shù)組越界 printf("%d\n", sizeof(&arr));//&arr取得是整個(gè)數(shù)組的地址 printf("%d\n", sizeof(&arr[0]));//取的是首元素的地址,相當(dāng)于指針 printf("%d\n", sizeof(parr));//parr指整個(gè)數(shù)組。 return 0; }
指針變量p所指向的變量類型為char,指針數(shù)組parr中存儲(chǔ)的指針變量的類型為char時(shí)候:
signed與unsigned 關(guān)鍵字
有符號(hào)整數(shù)vs無(wú)符號(hào)整數(shù)
char
unsigned char//無(wú)符號(hào)的字符類型
//取值范圍是0~255
//無(wú)符號(hào)表示二進(jìn)制的最高位不表示正負(fù),該整型只為正數(shù)。
//但可以儲(chǔ)存負(fù)數(shù),只是值會(huì)變成很大的正數(shù)
signed char//有符號(hào)字符
//取值范圍是-128~127
//因?yàn)樽址谋举|(zhì)是ASCII碼值,在內(nèi)存中以ASCII碼值進(jìn)行存儲(chǔ),所以劃分到整型家族
short
unsigned short [int]//無(wú)符號(hào)短整型
signed short [int]//有符號(hào)短整型
int
unsigned int//無(wú)符號(hào)整型
signed int//有符號(hào)整型
long
unsigned long [int]//無(wú)符號(hào)長(zhǎng)整型
signed long [int]//有符號(hào)整型
long long
unsigned long long [int]//無(wú)符號(hào)更長(zhǎng)的整型
signed long long [int] //有符號(hào)更長(zhǎng)的整型
char到底是signed char (取值范圍-128~127)還是unsigned char(取值范圍0~255)
標(biāo)準(zhǔn)是為定義的,取決于編譯器的實(shí)現(xiàn),小沐所使用的VS2019環(huán)境的char是signed char。
char a;// signed char a 或者 unsigned char a
int 標(biāo)準(zhǔn)定義是 signed int ,有符號(hào)整型,4個(gè)字節(jié),32個(gè)比特位
int a = 10;//signed int a //轉(zhuǎn)換成二進(jìn)制是00000000000000000000000000001010
整形在內(nèi)存的存儲(chǔ)
一個(gè)變量的創(chuàng)建是要在內(nèi)存中開(kāi)辟空間的,空間的大小是根據(jù)不同的類型而決定的。
那么,數(shù)據(jù)在所開(kāi)辟內(nèi)存中到底是如何存儲(chǔ)的呢?
計(jì)算機(jī)存儲(chǔ)數(shù)值時(shí)時(shí)存儲(chǔ)的該數(shù)值的二進(jìn)制的補(bǔ)碼的,而補(bǔ)碼是通過(guò)原碼和反碼進(jìn)行換算得到的。
任何數(shù)據(jù)在計(jì)算機(jī)中,都必須轉(zhuǎn)換成二進(jìn)制,計(jì)算機(jī)只認(rèn)識(shí)二進(jìn)制。
原碼
直接將數(shù)值按照正負(fù)數(shù)的形式翻譯成二進(jìn)制就可以得到原碼。
反碼
將原碼的符號(hào)位不變,其他位依次按位取反就可以得到反碼。
補(bǔ)碼
反碼+1就得到補(bǔ)碼。
int a = 10; //00000000000000000000000000001010 a的原碼 //00000000000000000000000000001010 a的反碼 //00000000000000000000000000001010 a的補(bǔ)碼 //0x0000000a int b = -10; //10000000000000000000000000001010 b的原碼 //0x8000000a //11111111111111111111111111110101 b的反碼 //0xfffffff5 //11111111111111111111111111110110 b的補(bǔ)碼 //0xfffffff6
符號(hào)位+數(shù)據(jù)位
有符號(hào)數(shù)且正數(shù),原碼,反碼和補(bǔ)碼相同。
有符號(hào)數(shù)且負(fù)數(shù),原碼,反碼和補(bǔ)碼不相同,需要通過(guò)計(jì)算轉(zhuǎn)換。計(jì)算機(jī)內(nèi)存儲(chǔ)的整型必須是補(bǔ)碼,符號(hào)位要參與計(jì)算的。
無(wú)符號(hào)數(shù):沒(méi)有符號(hào)位,原碼,反碼和補(bǔ)碼相同。
int a = 20;
int b = -10;
我們知道,編譯器為 a 分配四個(gè)字節(jié)的空間。那如何存儲(chǔ)呢?
首先,對(duì)于有符號(hào)數(shù),一定要能表示該數(shù)據(jù)是正數(shù)還是負(fù)數(shù)。所以我們一般用最高比特位來(lái)進(jìn)行充當(dāng)符號(hào)位。
原碼、反碼、補(bǔ)碼
計(jì)算機(jī)中的有符號(hào)數(shù)有三種表示方法,即原碼、反碼和補(bǔ)碼。
三種表示方法均有符號(hào)位和數(shù)值位兩部分,符號(hào)位都是用0表示“正”,用1表示“負(fù)”,而數(shù)值位三種表示方法各不相同。
如果一個(gè)數(shù)據(jù)是負(fù)數(shù),那么就要遵守下面規(guī)則進(jìn)行轉(zhuǎn)化:
原碼:直接將二進(jìn)制按照正負(fù)數(shù)的形式翻譯成二進(jìn)制就可以。
反碼:將原碼的符號(hào)位不變,其他位依次按位取反就可以得到了。
補(bǔ)碼:反碼+1就得到補(bǔ)碼。
如果一個(gè)數(shù)據(jù)是正數(shù),那么它的原反補(bǔ)都相同。
無(wú)符號(hào)數(shù):不需要轉(zhuǎn)化,也不需要符號(hào)位,原反補(bǔ)相同。
對(duì)于整形來(lái)說(shuō):數(shù)據(jù)存放內(nèi)存中其實(shí)存放的是補(bǔ)碼。
//字面值轉(zhuǎn)補(bǔ)碼
int a = 20;
//20是正整數(shù)
//0000 0000 0000 0000 0000 0000 0001 0100
int b = -10;
//-10是正整數(shù)
//1000 0000 0000 0000 0000 0000 0000 1010
//1111 1111 1111 1111 1111 1111 1111 0101
//1111 1111 1111 1111 1111 1111 1111 0110
補(bǔ)碼轉(zhuǎn)原碼
方法一:先-1,在符號(hào)位不變,按位取反。
方法二:將原碼到補(bǔ)碼的過(guò)程在來(lái)一遍。
原反補(bǔ)轉(zhuǎn)換需要通過(guò)計(jì)算機(jī)硬件來(lái)完成,
可以使用一條硬件電路就能完成原反補(bǔ)碼的轉(zhuǎn)換。
存儲(chǔ)的本質(zhì)
#include<stdio.h> int main() { unsigned int a = -10; //1000 0000 0000 0000 0000 0000 0000 1010-- -10的原碼 //1111 1111 1111 1111 1111 1111 1111 0110-- -10的補(bǔ)碼 printf("%d\n", a); printf("%u\n", a); return 0; }
無(wú)符號(hào)整型變量a定義時(shí),先有空間,再有內(nèi)容,先將內(nèi)容轉(zhuǎn)換成二進(jìn)制。 整型再存儲(chǔ)的時(shí)候,空間不關(guān)心內(nèi)容的。
在將數(shù)據(jù)保存在空間內(nèi)的時(shí)候,數(shù)據(jù)已經(jīng)被轉(zhuǎn)換成二進(jìn)制的補(bǔ)碼。
數(shù)據(jù)帶上類型才有意義。類型覺(jué)得了如何解釋空間內(nèi)部保存的二進(jìn)制序列。
變量的類型什么時(shí)候起效果?
在讀取數(shù)據(jù)的過(guò)程中,變量的類型起效果。
//變量的存和取過(guò)程的結(jié)論:
//存:字面數(shù)據(jù)必須先轉(zhuǎn)成補(bǔ)碼,在放入空間當(dāng)中。所以,所謂符號(hào)位,完全看數(shù)據(jù)本身是否攜帶±號(hào)。和變量是否有符號(hào)
無(wú)關(guān)!
//取:取數(shù)據(jù)一定要先看變量本身類型,然后才決定要不要看最高符號(hào)位。如果不需要,直接二進(jìn)制轉(zhuǎn)成十進(jìn)制。如果需要,則需要轉(zhuǎn)成原碼,然后才能識(shí)別。(當(dāng)然,最高符號(hào)位在哪里,又要明確大小端)
十進(jìn)制二進(jìn)制快速轉(zhuǎn)化
口訣:1后面跟n個(gè)0,就是2的n次方
67->64++1-->2^6+2^1+2^0
0000 0000 0000 0000 0000 0000 00100 0011
1->2^0
10->2^1
100->2^2
1000->2^3
后面跟n給比特位就是2^n
2^9->1000000000
為什么存儲(chǔ)的是補(bǔ)碼
在計(jì)算機(jī)系統(tǒng)中,數(shù)值一律用補(bǔ)碼來(lái)表示和存儲(chǔ)。原因在于,使用補(bǔ)碼,可以將符號(hào)位和數(shù)值域統(tǒng)一處理;
同時(shí),加法和減法也可以統(tǒng)一處理(CPU只有加法器)。此外,補(bǔ)碼與原碼相互轉(zhuǎn)換,其運(yùn)算過(guò)程是相同的,不需要額外的硬件電路。
大小端
什么大端小端:
大端(存儲(chǔ))模式,是指數(shù)據(jù)的低位保存在內(nèi)存的高地址中,而數(shù)據(jù)的高位,保存在內(nèi)存的低地址中;
小端(存儲(chǔ))模式,是指數(shù)據(jù)的低位保存在內(nèi)存的低地址中,而數(shù)據(jù)的高位,,保存在內(nèi)存的高地址中。
例如:
0x11223344
為什么有大端和小端:
因?yàn)樵谟?jì)算機(jī)系統(tǒng)中,我們是以字節(jié)為單位的,每個(gè)地址單元都對(duì)應(yīng)著一個(gè)字節(jié),一個(gè)字節(jié)為8 bit。但是在C語(yǔ)言中除了8 bit的char之外,還有16 bit的short型,32 bit的long型(要看具體的編譯器),另外,對(duì)于位數(shù)大于8位的處理器,例如16位或者32位的處理器,由于寄存器寬度大于一個(gè)字節(jié),那么必然存在著一個(gè)如何將多個(gè)字節(jié)安排的問(wèn)題。因此就導(dǎo)致了大端存儲(chǔ)模式和小端存儲(chǔ)模式。
例如:一個(gè) 16bit 的 short 型 x ,在內(nèi)存中的地址為 0x0010 , x 的值為 0x1122 ,那么 0x11 為高字節(jié), 0x22 為低字節(jié)。對(duì)于大端模式,就將 0x11 放在低地址中,即 0x0010 中, 0x22 放在高地址中,即 0x0011 中。小端模式,剛好相反。我們常用的 X86 結(jié)構(gòu)是小端模式,而 KEIL C51 則為大端模式。很多的ARM,DSP都為小端模式。有些ARM處理器還可以由硬件來(lái)選擇是大端模式還是小端模式。
到此這篇關(guān)于C語(yǔ)言詳解關(guān)鍵字sizeof與unsigned及signed的用法的文章就介紹到這了,更多相關(guān)C語(yǔ)言 sizeof unsigned signed內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
鏈接庫(kù)動(dòng)態(tài)鏈接庫(kù)詳細(xì)介紹
靜態(tài)鏈接庫(kù).lib和動(dòng)態(tài)鏈接庫(kù).dll。其中動(dòng)態(tài)鏈接庫(kù)在被使用的時(shí)候,通常還提供一個(gè).lib,稱為引入庫(kù),它主要提供被Dll導(dǎo)出的函數(shù)和符號(hào)名稱,使得鏈接的時(shí)候能夠找到dll中對(duì)應(yīng)的函數(shù)映射2012-11-11利用C語(yǔ)言實(shí)現(xiàn)2048小游戲的方法
2048是比較流行的一款數(shù)字游戲,相信對(duì)大家來(lái)說(shuō)都不陌生,這篇文章給大家分享了利用C語(yǔ)言實(shí)現(xiàn)2048小游戲的方法,對(duì)大家學(xué)習(xí)理解C語(yǔ)言具有一定的參考借鑒價(jià)值,有需要的朋友們下面來(lái)一起看看吧。2016-10-10C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易掃雷游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易掃雷游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-03-03詳解C++編程中的靜態(tài)成員與可變數(shù)據(jù)成員
這篇文章主要介紹了詳解C++編程中的靜態(tài)成員與可變數(shù)據(jù)成員,是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2016-01-01簡(jiǎn)述C++中虛擬函數(shù)的內(nèi)存分配機(jī)制
這篇文章主要介紹了簡(jiǎn)述C++中虛擬函數(shù)的內(nèi)存分配機(jī)制,幫助大家更好的理解和學(xué)習(xí)c++,感興趣的朋友可以了解下2020-08-08