欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言中數(shù)據(jù)在內(nèi)存如何存儲(chǔ)

 更新時(shí)間:2021年12月09日 08:36:26   作者:頭疼的太陽花  
本文詳細(xì)講解了C語言中數(shù)據(jù)在內(nèi)存如何存儲(chǔ),文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

數(shù)據(jù)類型

常見的數(shù)據(jù)類型

常見的數(shù)據(jù)類型 字節(jié)
char 字符數(shù)據(jù)類型 1
short 短整型 2
int 整形 4
long 長(zhǎng)整型 4
long long 更長(zhǎng)的整形 8
float 浮點(diǎn)型 4
double 雙精度浮點(diǎn)型 8

注意:

  • C語言里面沒有字符串類型
  • 關(guān)于int和long的大?。篊語言只是規(guī)定了:sizeof(long)>=sizeof(int)
  • 布爾類型(_Bool)(C99引入)專門用來表示真假,但是在C語言中不需要布爾類型也可以表示真假
#include<stdbool.h>
int main()
{
    _Bool flag = false;
    _Bool flag2 = true;
    if(flag)
    {
        printf("haha\n");
	}
    if(flag2)
    {
        printf("hehe\n");
	}
return 0;
}//只打印了hehe

類型的基本歸類

整形

char也屬于整形(每一個(gè)字符在儲(chǔ)存的時(shí)候是儲(chǔ)存他所對(duì)應(yīng)的ascll值,ascll是整數(shù))

char unsigned char signed char
short unsigned short signed short
int unsigned int signed int
long unsigned long signed long

有符號(hào)數(shù)和無符號(hào)數(shù)

有符號(hào)數(shù)
int main()
{
	int a = 10;
    int a = -10;
	return 0;
}//a是一個(gè)有符號(hào)數(shù),它可以儲(chǔ)存正負(fù)整數(shù)

//int ===> signed int
//short ===> signed short
//long ===> signed long

無符號(hào)數(shù)

有一些變量只有正數(shù)由意義,例如年齡,價(jià)格。定義這些變量的時(shí)候就可以用無符號(hào)數(shù)定義 ,無符號(hào)數(shù)只能存儲(chǔ)正數(shù)。

int main()
{
    unsigned int a = 10;
    //無符號(hào)變量只能儲(chǔ)存正數(shù)
    a = -10;
    //即使這里輸入了一個(gè)負(fù)數(shù),它也會(huì)把這個(gè)負(fù)數(shù)轉(zhuǎn)化成一個(gè)正數(shù)(不是簡(jiǎn)單的去掉符號(hào),這是關(guān)于二進(jìn)制的計(jì)算)
    return 0;
}

是否char 等于signed char呢?

答案:取決于編譯器

  • 我們會(huì)發(fā)現(xiàn)這樣一件事:
    int 就是 signed int
    short 就是 signed short
    long 就是 signed long
  • char 等于signed char還是unsigned char 取決于編譯器,不同的編譯器可能是不同的結(jié)果,常見的編譯器下是等于signed char
對(duì)于有符號(hào)數(shù)字和無符號(hào)數(shù)字的打印

打印無符號(hào)數(shù)應(yīng)該用%u

%u和%d打印的解讀方式不同:

  • 使用%d 時(shí),會(huì)認(rèn)為這是一個(gè)有符號(hào)數(shù),打印的時(shí)候會(huì)認(rèn)為二進(jìn)制中第一位是符號(hào)位;
  • 使用%u時(shí),會(huì)認(rèn)為這是一個(gè)無符號(hào)數(shù)據(jù),會(huì)認(rèn)為整個(gè)二進(jìn)制序列都是有效位。
#include<stdio.h>
int main()
{
    unsigned int a = 10;
    printf("%u",a);//正確的形式
    
    //如果存儲(chǔ)了一個(gè)-10進(jìn)去會(huì)怎么樣
    a = -10;
    printf("%u",a);
    //會(huì)打印4294967286,而這個(gè)數(shù)據(jù)不是隨機(jī)數(shù)
    return 0;
}

為什么無符號(hào)整形儲(chǔ)存 -10 的時(shí)候會(huì)打印出來4284967286(并不是隨機(jī)數(shù))?

%u在解讀的時(shí)候認(rèn)為此時(shí)a仍然存儲(chǔ)的是正數(shù),解讀了a的補(bǔ)碼。在本章后面介紹原反補(bǔ)嗎的時(shí)候在詳細(xì)解釋細(xì)節(jié)。

浮點(diǎn)型

浮點(diǎn)型 大小
float 4
double 8

構(gòu)造類型(自定義類型)

構(gòu)造類型
數(shù)組 數(shù)組名去掉后剩下的就是數(shù)組的類型
結(jié)構(gòu)體 struct
枚舉類型 enum
聯(lián)合(聯(lián)合體)類型 union

指針類型

指針類型
char* pc
int * pi
float* pf
void* pv

空類型

void表示空類型(無類型)

通常應(yīng)用于函數(shù)的返回類型,函數(shù)的參數(shù),指針類型

整形在內(nèi)存中的存儲(chǔ)

int a = 10;
int b = -10;

然后我們觀察a、b在內(nèi)存中的儲(chǔ)存

數(shù)據(jù)在內(nèi)存里面是以二進(jìn)制儲(chǔ)存的,但是編譯器是以十六進(jìn)制展現(xiàn)給我們看的:

a在內(nèi)存中的值是 :0a 00 00 00

b在內(nèi)存中的值是: f6 ff ff ff

為什么是這樣的值呢?下面介紹整數(shù)的原碼、反碼、補(bǔ)碼。

原碼,反碼,補(bǔ)碼

整數(shù)二進(jìn)制有3種表示形式,而內(nèi)存中存儲(chǔ)的是二進(jìn)制的補(bǔ)碼

例如 1 的原碼:

00000000 00000000 00000000 00000001

正整數(shù)

正整數(shù)的原碼、反碼和補(bǔ)碼相同

負(fù)整數(shù)

  • 原碼:按照一個(gè)數(shù)的正負(fù)直接寫出來的二進(jìn)制就是原碼
  • 反碼:符號(hào)位不變,其他位按位取反 (并不是按位取反)
  • 補(bǔ)碼:反碼的二進(jìn)制序列加1

從原碼轉(zhuǎn)換成補(bǔ)碼:先取反再加一。

從補(bǔ)碼轉(zhuǎn)換成原碼:可以先減一再取反,也可以先取反再加一(和原碼轉(zhuǎn)換成補(bǔ)碼的過程相同)。

類型 數(shù)據(jù):15 數(shù)據(jù):-15
原碼 00000000 00000000 00000000 00001111 10000000 00000000 00000000 00001111
反碼 00000000 00000000 00000000 00001111 11111111 11111111 11111111 11110000
補(bǔ)碼 00000000 00000000 00000000 00001111 11111111 11111111 11111111 11110001

解釋為什么%u打印-10;會(huì)出現(xiàn)4294967286

用上面的方法我們就可以計(jì)算出-10的補(bǔ)碼:

數(shù)據(jù) 補(bǔ)碼
10 11111111 11111111 11111111 11110110

回到最開始使用%u打印-10會(huì)打印成4294967286,是因?yàn)樵谑褂?u的時(shí)候,不會(huì)解讀符號(hào)位,會(huì)將整個(gè)32位二進(jìn)制都當(dāng)作有效位,讀出一個(gè)數(shù)據(jù),而這個(gè)數(shù)據(jù)就是4294967286。

同時(shí)回到剛才a,b的值

int main()
{
int a = 10;
int b = -10;
    //a: 00000000 00000000 00000000 00001010
    //b: 11111111 11111111 11111111 11110110
}
//四個(gè)二進(jìn)制位轉(zhuǎn)換成一個(gè)十六進(jìn)制位
//a: 00 00 00 0a
//b: ff ff ff f6

為什么和在內(nèi)存界面看到的不同呢?

內(nèi)存界面和我們計(jì)算出來的順序是相反的:

數(shù)據(jù) 計(jì)算結(jié)果 內(nèi)存
10 00 00 00 0a 0a 00 00 00
-10 ff ff ff f6 f6 ff ff ff

為什么會(huì)倒著存進(jìn)去?

這就和字節(jié)序有關(guān),下面我們來了解字節(jié)序

大小端字節(jié)序

當(dāng)儲(chǔ)存的內(nèi)容超過一個(gè)字節(jié)的時(shí)候,儲(chǔ)存的時(shí)候就有順序

(一個(gè)char類型的數(shù)據(jù)是沒有字節(jié)序。char類型的數(shù)據(jù)只有一個(gè)字節(jié),沒有順序)

機(jī)器有兩種對(duì)字節(jié)的存儲(chǔ)順序:

  • 大端字節(jié)序存儲(chǔ):
    低字節(jié)數(shù)據(jù)存放在高地址處,高字節(jié)數(shù)據(jù)存放在低地址處
  • 小端字節(jié)序存儲(chǔ)
    低字節(jié)數(shù)據(jù)存放在低地址處,高字節(jié)數(shù)據(jù)存放在高地址處

我們用下面這個(gè)例子來解釋:

int main()
{
    int a = 0x11223344;//0x開頭說明是十六進(jìn)制數(shù)字
    //再內(nèi)存界面看到:44 33 22 11
   
    return 0;
}

而我在觀察內(nèi)存的時(shí)候發(fā)現(xiàn)我的機(jī)器是按照方式2進(jìn)行存儲(chǔ)的,所以我的機(jī)器是采用的小端字節(jié)序。

那么有什么方法可以快速判斷自己當(dāng)前使用的機(jī)器屬于哪一種字節(jié)序呢?

設(shè)計(jì)一個(gè)小程序判斷當(dāng)前機(jī)器屬于哪種字節(jié)序

#include<stdio.h>
int main()
{
    int a = 1;
    //a的十六進(jìn)制是 00 00 00 01
    //如果是大端那么內(nèi)存中為:00 00 00 01
    //如果是小端那么內(nèi)存中為:01 00 00 00
    //只需要判斷第一個(gè)字節(jié)的內(nèi)容是不是1
    char*pc = (char*)&a;
    //強(qiáng)制類型轉(zhuǎn)換截取了a的第一個(gè)字節(jié)
    if(*pc)//也可以是:if(*(char*)&a)
    {
        printf("小端");
	}
    else
    {
        printf("大端");
	}
        
	return 0;
}

儲(chǔ)存時(shí)數(shù)據(jù)發(fā)生截?cái)嘁约罢吞嵘?/h3>

例題1

int main()
{
	char a = -1;
	signed char b = -1;
	unsigned char c = -1;
	printf("%d %d %d ",a,b,c);//會(huì)打印出-1 -1 255
    return 0;
}

解釋:

  • 第一步:
    這里我們將三個(gè)相同的整數(shù) -1 分別存進(jìn)了兩種類型的變量,(在我所使用的VS2019編譯器下char和signed char等價(jià)),而這兩種類型又都屬于char類型
  • 第二步:
    char 類型的變量只能儲(chǔ)存一個(gè)字節(jié)(8個(gè)比特位)大小的數(shù)據(jù),但是 -1 是整形(包含32個(gè)比特位),
    這里就需要發(fā)生數(shù)據(jù)截?cái)啵?-1 的二進(jìn)制補(bǔ)碼是11111111 11111111 11111111 11111111
    截?cái)啵簩⒀a(bǔ)碼的最后八位賦值給變量a、b、c。
  • 第三步:
    這里需要將char類型的數(shù)據(jù)以%d的方式打印,但是%d只能解讀整數(shù)數(shù)據(jù)(整數(shù)有四個(gè)字節(jié)),而char類型的三個(gè)變量都只有一個(gè)字節(jié),所以這里會(huì)發(fā)生整型提升:
    整形提升:對(duì)于有符號(hào)數(shù)據(jù),高位補(bǔ)符號(hào)位,對(duì)于無符號(hào)數(shù)據(jù):高位補(bǔ)0
數(shù)據(jù)(變量) 整形提升前 整形提升后(補(bǔ)碼) 原碼代表的數(shù)據(jù)
a/b 11111111 11111111 11111111 11111111 11111111 -1
c 11111111 00000000 00000000 00000000 11111111 255

%d打印的時(shí)候會(huì)認(rèn)為這就是要打印數(shù)據(jù)的補(bǔ)碼,按照打印正常整數(shù)的形式打印這三個(gè)變量

例題2

#include<stdio.h>
int main()
{
    
    char a = -128;
    printf("%u",a);//會(huì)打印4294967168
    return 0;
}

解釋:

  • 第一步:
    觀察數(shù)據(jù): -128 是一個(gè)整數(shù),二進(jìn)制有32位 : 但是接受這個(gè)數(shù)據(jù)的變量是一個(gè)char類型的變量(只能接受8個(gè)比特位)
  • 第二步:
    數(shù)據(jù)的截?cái)啵?/li>
數(shù)據(jù) 二進(jìn)制(補(bǔ)碼) 截?。╝儲(chǔ)存的部分)
-128 11111111 11111111 11111111 10000000 10000000

聯(lián)想:這里如果是a = 128,那么階段后的值仍然是10000000

  • 第三步:
    打印整數(shù)(四個(gè)字節(jié)),所以這里需要發(fā)生整形提升(a是有符號(hào)char,高位補(bǔ)符號(hào)位)
數(shù)據(jù)(變量) 整形提升前 整形提升后(補(bǔ)碼)
a 10000000 11111111 11111111 11111111 10000000
  • 第四步:
    %u的形式打印這個(gè)變量,因?yàn)?u應(yīng)該打印的是無符號(hào)整數(shù),且打印的時(shí)候認(rèn)為整個(gè)32位全為有效位,
    就會(huì)打印出4294967168

浮點(diǎn)型在內(nèi)存中的存儲(chǔ)

常見的浮點(diǎn)數(shù) 例子
字面浮點(diǎn)數(shù) 3.14159
科學(xué)計(jì)數(shù)法的表示形式 1E10(1乘以10的10次方)

注意:

  • 在浮點(diǎn)型數(shù)據(jù)后面加了f是float類型,不加則默認(rèn)是double類型
  • %f和%lf默認(rèn)小數(shù)點(diǎn)后六位

浮點(diǎn)型和整形在內(nèi)存中的儲(chǔ)存方式不同

我們通過下面這個(gè)例題來探究浮點(diǎn)型和整形在內(nèi)存中的儲(chǔ)存方式有什么不同

#include<stdio.h>
int main()
{

	int n = 9;
	float* pf = (float*)&n;
    //第一組
	printf("n = %d\n", n);    //打印出:9
	printf("*pf = %f\n", *pf);//打印出:0.000000
	//第二組
	*pf = 9.0;
	printf("n = %d\n", n);	  //打印出:1091567616
	printf("*pf = %f\n", *pf);//打印出:9.000000

	return 0;
}

為什么會(huì)出現(xiàn)這樣的情況?

回答這個(gè)問題前,先來了解浮點(diǎn)型的二進(jìn)制存儲(chǔ)形式:

國(guó)際標(biāo)準(zhǔn)電氣電子工程師學(xué)會(huì)(IEEE):任何一個(gè)二進(jìn)制浮點(diǎn)數(shù)V都可以表示成下面的形式

  • 表示形式:(-1)^S * M * 2^E
  • (-1)^S表示符號(hào)位,當(dāng)S為0 時(shí)表示正數(shù),當(dāng)S為1時(shí),表示負(fù)數(shù)
  • M表示有效數(shù)字,大于等于1,小于等于2
  • 2^E表示指數(shù)位
(5.5)十進(jìn)制 (5.5)二進(jìn)制
5.5 101.1
5.5*(10^1) 1.011*(2^2)
十進(jìn)制浮點(diǎn)數(shù):5.5
轉(zhuǎn)化成二進(jìn)制:101.1
可以寫成:(-1)^0 * 1.011 * (2^2)
S = 0
M = 1.011
E = 2
只需要儲(chǔ)存SME三個(gè)值
  • IEEE浮點(diǎn)數(shù)標(biāo)準(zhǔn)定義了兩種基本的格式:以四個(gè)字節(jié)表示的的單精度格式和八個(gè)字節(jié)表示的雙精度格式

單精度浮點(diǎn)數(shù)儲(chǔ)存格式(32位)

第一位 接著8位 剩下23位
符號(hào)位 指數(shù)位 有效位

雙精度浮點(diǎn)數(shù)儲(chǔ)存格式(64位)

第一位 接著11位 剩下52位
符號(hào)位 指數(shù)位 有效位

IEEE754對(duì)于有效數(shù)字M和指數(shù)E有一些特別的規(guī)定:

  • 關(guān)于M:
    1.我們已經(jīng)知道1<=M<2,也即是說M一定可以寫成這樣的形式:1.xxxxxx
    其中xxxxxx表示小數(shù)點(diǎn)后面的部分
    2.在計(jì)算機(jī)內(nèi)部?jī)?chǔ)存M時(shí),由于第一位總是1,所以把這個(gè)1省略,只保存后面的小數(shù)部分,這樣可以節(jié)約一位有效數(shù)字,這樣的話儲(chǔ)存的數(shù)據(jù)精度就可以提升一位:例如在單精度浮點(diǎn)型存儲(chǔ)格式中,最后23位作為有效位,但是儲(chǔ)存在計(jì)算機(jī)的數(shù)據(jù)精度是24位
  • 關(guān)于E:
    計(jì)算機(jī)會(huì)認(rèn)為這是一個(gè)無符號(hào)數(shù),但是十幾行會(huì)存在很多E取負(fù)數(shù)的情況,所以IEEE754規(guī)定:存入內(nèi)存時(shí),E的真實(shí)值必須在加上一個(gè)中間數(shù) ,對(duì)于單精度,這個(gè)中間數(shù)(也叫做偏移量)是127,對(duì)于雙精度,這個(gè)中間數(shù)是1023
    例如:對(duì)于十進(jìn)制的數(shù)字0.5,它的二進(jìn)制是0.1,E= -1;那么我們就需要把-1在加上127得到126后,將126儲(chǔ)存在指數(shù)位

拿出這些儲(chǔ)存的數(shù)據(jù)(三種情亂)

情況一:E不全為0或不為全1

  • E: 指數(shù)位值減去127(1023)得到真實(shí)值
  • M: 有效位的數(shù)值前面加上1.

情況二:E全為0

  • E:
    真實(shí)的E是一個(gè)十分小的數(shù)字,接近0;
    這時(shí)候不用計(jì)算,E直接就等于1-127(1-1023)就是它的真實(shí)值
  • M:
    M不再在前面加上1,而是還原成0.XXXXXX的小數(shù),這樣做是為了表示正負(fù)0,以及接近于0的很小的數(shù)字。

情況三:E為全1

  • 真實(shí)的E是一個(gè)十分大的數(shù)字,代表正負(fù)無窮大的數(shù)字

解釋上面的例子

  • 第一組為什么以%f打印整數(shù)9,會(huì)打印出0.000000?

原因:

此時(shí)E為全0,是一個(gè)會(huì)被判定成一個(gè)十分小的數(shù)據(jù),所以打印0.000000

  • 為什么第二組中以%d的形式打印*pf時(shí),會(huì)打印出1091567616?

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 排列和組合算法的實(shí)現(xiàn)方法_C語言經(jīng)典案例

    排列和組合算法的實(shí)現(xiàn)方法_C語言經(jīng)典案例

    下面小編就為大家?guī)硪黄帕泻徒M合算法的實(shí)現(xiàn)方法_C語言經(jīng)典案例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-09-09
  • 基于Matlab實(shí)現(xiàn)山脊圖的繪制

    基于Matlab實(shí)現(xiàn)山脊圖的繪制

    這篇文章主要介紹了如何利用Matlab實(shí)現(xiàn)山脊圖的繪制,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Matlab有一定的幫助,需要的可以參考一下
    2022-05-05
  • android studio創(chuàng)建C++項(xiàng)目的實(shí)現(xiàn)示例

    android studio創(chuàng)建C++項(xiàng)目的實(shí)現(xiàn)示例

    本文主要介紹了android studio創(chuàng)建C++項(xiàng)目的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • C++實(shí)現(xiàn)景區(qū)信息管理系統(tǒng)

    C++實(shí)現(xiàn)景區(qū)信息管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)景區(qū)信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • C語言中K-means算法實(shí)現(xiàn)代碼

    C語言中K-means算法實(shí)現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了C語言中K-means算法的實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • 實(shí)現(xiàn)C語言常用字符串庫函數(shù)

    實(shí)現(xiàn)C語言常用字符串庫函數(shù)

    這篇文章主要為大家介紹了如何實(shí)現(xiàn)C語言常用字符串庫函數(shù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11
  • C++類和對(duì)象到底是什么

    C++類和對(duì)象到底是什么

    C++ 是一門面向?qū)ο蟮木幊陶Z言,理解 C++,首先要理解類(Class)和對(duì)象(Object)這兩個(gè)概念。下面和小編一起來學(xué)習(xí)吧
    2021-09-09
  • STL  priority_queue(優(yōu)先隊(duì)列)詳解

    STL priority_queue(優(yōu)先隊(duì)列)詳解

    這篇文章主要介紹了 STL priority_queue(優(yōu)先隊(duì)列)詳解的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • c++ vector模擬實(shí)現(xiàn)代碼

    c++ vector模擬實(shí)現(xiàn)代碼

    vector是C++ STL中一個(gè)非常重要的容器,了解 vector 的底層實(shí)現(xiàn)原理,可以很好的幫助我們更加熟練的使用vector。這篇文章通過實(shí)例代碼給大家介紹c++ vector模擬實(shí)現(xiàn),感興趣的朋友跟隨小編一起看看吧
    2020-02-02
  • C++ LeetCode1805字符串不同整數(shù)數(shù)目

    C++ LeetCode1805字符串不同整數(shù)數(shù)目

    這篇文章主要為大家介紹了C++ LeetCode1805字符串不同整數(shù)數(shù)目,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12

最新評(píng)論