亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

 更新時(shí)間:2021年09月28日 11:15:11   作者:Dooo_yh  
本篇文章是C語言編程篇,主要為大家介紹C語言編程中數(shù)據(jù)在內(nèi)存中存儲(chǔ)解析,有需要的朋友可以借鑒參考下,希望可以有所幫助

文章摘要

本文通過內(nèi)存底層原理,幫你透徹了解數(shù)據(jù)存儲(chǔ)進(jìn)內(nèi)存與從內(nèi)存中讀取的區(qū)別以及不同數(shù)據(jù)類型下數(shù)據(jù)計(jì)算、賦值的變化情況
要透徹理解這些,必須知道隱式類型轉(zhuǎn)換以及機(jī)器大小端的概念,本文會(huì)對此做簡單介紹(這兩個(gè)概念對C語言數(shù)據(jù)的深度理解非常重要)

一、C語言的數(shù)據(jù)類型

數(shù)據(jù)類型基本分為:

1.整性

char  //字符本質(zhì)上是整型,只是char類型值截?cái)嚅_辟一個(gè)字節(jié)
	unsigned char
	signed char
short  //2字節(jié)
	unsigned short [int]
	signed short [int]
int  //4字節(jié)
	unsigned int
	signed int
long  //4字節(jié)
	unsigned long [int]
	signed long [int]

2.浮點(diǎn)型

float
double

3.構(gòu)造類型

數(shù)組類型
結(jié)構(gòu)體類型 struct
枚舉類型 enum
聯(lián)合類型 union

4.指針類型

int* pi;
char* pc;
float* pf;
void* pv;
...

5.空類型

void

二、隱式類型轉(zhuǎn)換

1.什么是隱式類型轉(zhuǎn)換

在C語言中,隱式類型轉(zhuǎn)換是編譯器自發(fā)的行為,它往往是從小到大的轉(zhuǎn)換,在數(shù)據(jù)類型上表現(xiàn)是少字節(jié)數(shù)據(jù)類型,轉(zhuǎn)換成多字節(jié)數(shù)據(jù)類型,保證數(shù)據(jù)的完整性;(面向?qū)ο笳Z言也有該概念,并且對于類也會(huì)有隱式類型轉(zhuǎn)換)一般來說,隱式類型轉(zhuǎn)換大體分為兩種:整性提升類型轉(zhuǎn)換

2.整型提升 

1.定義: C的整型算術(shù)運(yùn)算總是至少以缺省整型類型的精度來進(jìn)行的。為了獲得這個(gè)精度,表達(dá)式中的 字符(char類型1字節(jié)) 和 短整型(short int類型2字節(jié)) 操作數(shù)在使用之前被轉(zhuǎn)換為 普通整型(int類型4字節(jié)) ,這種轉(zhuǎn)換稱為整型提升。

通俗來說:無論數(shù)據(jù)類型是否為 char 、short int 、…,其在讀取到CPU進(jìn)行計(jì)算時(shí),都會(huì)先通過整性提升到32位計(jì)算,而結(jié)算結(jié)果的讀取位數(shù)取決于讀取的數(shù)據(jù)類型,若為char類型,則截?cái)嗳?位(bit).

【這里注意:通常CPU在計(jì)算時(shí),用的數(shù)據(jù)是源碼已翻譯后的補(bǔ)碼來計(jì)算】

2.整性提升是按照變量的數(shù)據(jù)類型(指自身類型,而不是數(shù)值類型)的符號位來提升

//eg1.負(fù)數(shù)的整性提升
char a = -1;  //char類型默認(rèn)為有符號類型
//其二進(jìn)制源碼為:1 000 0001
//        補(bǔ)碼為:1 111 1111
//整性提升時(shí),由于8bit的char類型數(shù)據(jù)中符號位為1;
//故提升為32位后 11111111 11111111 11111111 11111111;(補(bǔ)碼)

//eg2.正數(shù)的整性提升
char a = 1; 
//其二進(jìn)制源碼為:0 000 0001
//   補(bǔ)碼=源碼為:0 000 0001
//整性提升時(shí),由于8bit的char類型數(shù)據(jù)中符號位為0;
//故提升為32位后 00000000 00000000 00000000 00000001;(補(bǔ)碼)

3.截?cái)嗟木唧w體現(xiàn):

//eg3.
char c = -129;
printf("%d",c);

結(jié)果為:127

原因是:-129源碼為:1000 0000 0000 0000 0000 0000 1000 0001

在內(nèi)存中的補(bǔ)碼為:1111 1111 1111 1111 1111 1111 0111 1111

而字符變量c 只截?cái)?bit位 即c變量保存的是:0111 1111(補(bǔ)碼)

輸出d%位整型,且符號位為0

整型提升為0000 0000 0000 0000 0000 0000 0111 1111(補(bǔ)碼)

轉(zhuǎn)為源碼即為127

注意這里的截?cái)嘣瓌t與機(jī)器大小端有關(guān),且截?cái)嗍窃趦?nèi)存上對補(bǔ)碼進(jìn)行操作

3.類型轉(zhuǎn)換

1.概念:操作符兩邊的操作數(shù)屬于不同的類型,那么除非其中一個(gè)操作數(shù)的轉(zhuǎn)換為另一個(gè)操作數(shù)的類型,否則操作就無法進(jìn)行;而這種轉(zhuǎn)換就是類型轉(zhuǎn)換(編譯器自發(fā))

2.從下至上,自動(dòng)轉(zhuǎn)換

long double
double
float
unsigned long int
long int
unsigned int
int

3.【注意】這種類型轉(zhuǎn)換只是建立在運(yùn)算操作符之間,不然會(huì)出現(xiàn)不合理問題

eg4.
float f = 3.14;
int num = f;//隱式轉(zhuǎn)換,會(huì)有精度丟失

賦值情況下導(dǎo)致在高位的float類型轉(zhuǎn)為低位的int類型,導(dǎo)致精度丟失

三、機(jī)器大小端

1.什么是大小端

小端(存儲(chǔ))模式,是指數(shù)據(jù)的底位(低權(quán)值)保存在內(nèi)存的底地址中,而數(shù)據(jù)的高位(高權(quán)值),保存在內(nèi)存高地址中;

大多數(shù)機(jī)器都采用小端模式

大端(存儲(chǔ))模式,是指數(shù)據(jù)的底位(低權(quán)值)保存在內(nèi)存高的地址中,而數(shù)據(jù)的高位,保存在內(nèi)存低地址中;

2.大小端在截?cái)嗟膽?yīng)用

上文的eg3.中出現(xiàn)了截?cái)?,即字符c截?cái)嗾蛿?shù)值-129

//eg3.
char c = -129;

在這里插入圖片描述

我們將代碼中的整型a變量在內(nèi)存的地址儲(chǔ)存數(shù)據(jù)顯示出來,從內(nèi)存地址可以看出,序列從高到低遞增
a:補(bǔ)碼為 1111 1111 1111 1111 1111 1111 0111 1111

轉(zhuǎn)為16進(jìn)制后即為 ff ff ff 7f;(權(quán)值左邊最高,右邊最低

再將字符變量c內(nèi)存的地址儲(chǔ)存數(shù)據(jù)顯示出來,可以看出,由于char類型只有一字節(jié),會(huì)優(yōu)先從四字節(jié)a中截?cái)嗟刂纷畹偷囊蛔止?jié)

由圖看出它截?cái)嗔说偷刂防锏臄?shù)據(jù)7f,而7f也是低權(quán)值。
故,在vs2013中,采用的是小端原則

3.判斷當(dāng)前機(jī)器的字節(jié)序是大端還是小端

#include<stdio.h>
#include<Windows.h>
#pragma warning(disable:4996)

int check_sys()
{
	int i = 1;
	return (*(char*)&i);//注意,發(fā)生數(shù)據(jù)類型轉(zhuǎn)換
}

int main()
{
	int ret = check_sys();
	if (ret)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}

	system("pause");
	return 0;
}

【注意】(*(char*)&i);

這里是對指針的解引用時(shí),從內(nèi)存所取的字節(jié)大小由其指向的數(shù)據(jù)類型決定。 說白了就是 i 的地址從int *被強(qiáng)轉(zhuǎn)為char *,再解引用時(shí),其指向的數(shù)據(jù)類型從int變?yōu)閏har,因此顯示的數(shù)據(jù)會(huì)發(fā)生截?cái)啵?/p>

由上面的截?cái)喾绞轿覀兛梢灾溃?在內(nèi)存是以32位存儲(chǔ)的,按一字節(jié)來說,其高權(quán)值位為0、低權(quán)值位為1.故可以通過return傳參的1或0判斷大小端。

四、整型在內(nèi)存中的存儲(chǔ)

 1.原碼、反碼、補(bǔ)碼

一個(gè)數(shù)在計(jì)算機(jī)中的二進(jìn)制表示形式, 叫做這個(gè)數(shù)的機(jī)器數(shù)。機(jī)器數(shù)是帶符號的,在計(jì)算機(jī)用一個(gè)數(shù)的最高位存放符號, 正數(shù)為0, 負(fù)數(shù)為1.

比如,十進(jìn)制中的數(shù) +3 ,計(jì)算機(jī)字長為8位,轉(zhuǎn)換成二進(jìn)制就是00000011;

如果是 -3 ,就是 10000011

在C語言中,整型在計(jì)算機(jī)的儲(chǔ)存情況是按原反補(bǔ)的規(guī)則儲(chǔ)存,即對于整型來說,數(shù)據(jù)存放在內(nèi)存中其實(shí)是補(bǔ)碼。

計(jì)算機(jī)采用這種規(guī)則可以使數(shù)據(jù)運(yùn)算時(shí)的+ - * / 運(yùn)算都通過加法解決,這樣設(shè)計(jì)的計(jì)算機(jī)只需設(shè)計(jì)出加法模塊,大大節(jié)省成本。

具體規(guī)則如下:

1.正數(shù)

正數(shù)的原、反、補(bǔ)碼都相同,與原碼一樣

2.負(fù)數(shù)

原碼:該數(shù)的機(jī)器數(shù),最高位為符號位

反碼:原碼除符號位不變,其余位按位取反

補(bǔ)碼:反碼+1 

2.舉例實(shí)踐整型數(shù)據(jù)在內(nèi)存的存儲(chǔ)

//例1.嘗試判斷輸出結(jié)果是什么
int main()
{
	char a = -1;
	signed char b = -1;
	unsigned char c = -1;
	printf("a=%d,b=%d,c=%d\n", a, b, c);

	system("pause");
	return 0;
}

結(jié)果:

在這里插入圖片描述

例1解析:

-1在內(nèi)存的補(bǔ)碼:1111 1111 1111 1111 1111 1111 1111 1111

char a 、signed char b 、unsigned char c 存放時(shí)發(fā)生截?cái)?,其在?nèi)存的補(bǔ)碼均為:1111 1111

但是三位在以%d(整型)輸出時(shí),會(huì)發(fā)生整型提升,由原來的8位整型提升到32位,而整型提升時(shí)高位補(bǔ)0還是補(bǔ)1需看數(shù)據(jù)自身類型(有符號類型補(bǔ)符號位,無符號類型直接補(bǔ)0

char a 與 signed char b 均屬于有符號型,且符號位為1,補(bǔ)24位1

內(nèi)存數(shù)值為:1111 1111 1111 1111 1111 1111 1111 1111;輸出%d時(shí)反向推回原碼,答案即為 -1

unsigned char c 屬于無符號型,補(bǔ)24位0

內(nèi)存數(shù)值為:0000 0000 0000 0000 0000 0000 1111 1111;輸出%d時(shí)反向推回原碼,答案即為 255

//例2.嘗試判斷輸出結(jié)果是什么
int main()
{
	char a = 128;
	char b = -128;
	printf("a=%u,b=%u\n", a,b);
	
	system("pause");
	return 0;
}

結(jié)果:

在這里插入圖片描述

例2解析:

128在內(nèi)存的補(bǔ)碼:0000 0000 0000 0000 0000 0000 1000 0000

-128的內(nèi)存補(bǔ)碼: 1111 1111 1111 1111 1111 1111 1000 0000

char a 、char b 存放時(shí)發(fā)生截?cái)?,其在?nèi)存的補(bǔ)碼均為:1000 0000

%u(無符號整型)輸出時(shí),會(huì)發(fā)生整型提升,由原來的8位整型提升到32位

char a 與 char b 均屬于有符號型,且符號位為1,補(bǔ)24位1

內(nèi)存數(shù)值均為:1111 1111 1111 1111 1111 1111 1000 0000;輸出%u時(shí)反碼直接當(dāng)原碼,

答案即為 :

在這里插入圖片描述

//例3.嘗試判斷輸出結(jié)果是什么
int main()
{
	int i = -20;
	unsigned int j = 10;
	printf("i+j = %d\n", i + j);
	
	system("pause");
	return 0;
}

結(jié)果:

在這里插入圖片描述

例3解析:

-20在內(nèi)存的補(bǔ)碼:1111 1111 1111 1111 1111 1111 1110 1100

10在內(nèi)存的補(bǔ)碼:0000 0000 0000 0000 0000 0000 0000 1010

int i 與 unsigned int j 都是四字節(jié)類型變量故存儲(chǔ)時(shí)不會(huì)發(fā)生截?cái)啵?br />

但 ·i + j = 表達(dá)式會(huì)發(fā)生類型轉(zhuǎn)換,int 會(huì)自動(dòng)轉(zhuǎn)換為 unsigned int 類型計(jì)算

CPU中將兩變量補(bǔ)碼進(jìn)行相加得到:1111 1111 1111 1111 1111 1111 1111 0110

計(jì)算結(jié)果以%d(整型)輸出,反向推回原碼:1000 0000 0000 0000 0000 0000 0000 1010

答案即為 -10

//例4.嘗試判斷輸出結(jié)果是什么
int main()
{
	unsigned int i;
	for (i = 9; i >= 0; i--)
	{
		printf("%u\n", i);
	}

	system("pause");
	return 0;
}

結(jié)果:

在這里插入圖片描述

例4解析:

由于 i 變量時(shí) unsinged int 類型,因此其無符號位,

且 ·i >= 0 表達(dá)式會(huì)發(fā)生類型轉(zhuǎn)換,int 0 會(huì)自動(dòng)轉(zhuǎn)換為 unsigned int 類型計(jì)算

故其比較結(jié)果永遠(yuǎn)為真,因?yàn)闊o符號類型第32bit位(符號位)永遠(yuǎn)為0

for 循環(huán)條件永遠(yuǎn)滿族,答案即為死循環(huán)

//例5.嘗試判斷輸出結(jié)果是什么
int main()
{
	char a[1000];
	int i;
	for (i = 0; i <1000; i++)
	{
		a[i] = -1 - i;
	}
	printf("%d\n", strlen(a));

	system("pause");
	return 0;
}

結(jié)果:

在這里插入圖片描述

例5解析:

char a[1000]數(shù)組的每一位元素都是1字節(jié)的 char 類型,有字符位,故其保存的數(shù)值范圍:[-128,127];

-1-i 范圍從 -1到 -1000,但在循環(huán)體 a[i] = -1 - i中每次賦值都會(huì)發(fā)生截?cái)?,由下圖可知,char類型保存的數(shù)值依次遞減時(shí),-1 繼續(xù)減到 -128 ,128 減一位到 127,127 繼續(xù)減到0,0再減一位到 -1,繼續(xù)下一輪循環(huán);

在這里插入圖片描述

而該題的輸出時(shí)數(shù)組字符長度,strlen遇 ‘\0'(等價(jià)于數(shù)值0),而在初始化后的char a[1000]數(shù)組中,數(shù)值第一次出現(xiàn)0在a[255];

故答案為255

//例6.嘗試判斷輸出結(jié)果是什么
int main()
{
	unsigned char i = 0;
	for (i = 0; i <= 255; i++)
	{
		printf("%d ", i);
		Sleep(30);
	}

	system("pause");
	return 0;
}

結(jié)果:0-255無限循環(huán)

在這里插入圖片描述

例6解析:

由例5解析的圖可知:unsigned char 類型的變量 i 的取值范圍:[-128,127],永遠(yuǎn)小于255;

而%d輸出時(shí),無符號類型直接整型提升補(bǔ)24位0:

0000 0000 (0)轉(zhuǎn)為 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000(補(bǔ)),補(bǔ)碼轉(zhuǎn)原碼:符號位為0,原碼與補(bǔ)碼一樣,值為0;

1000 0000(-128)轉(zhuǎn)為0000 0000 0000 0000 0000 0000 0000 0000 1000 0000(補(bǔ)),補(bǔ)碼轉(zhuǎn)原碼:1000 0000 0000 0000 0000 0000 1000 0000,值為128;

0111 1111(127)轉(zhuǎn)為0000 0000 0000 0000 0000 0000 0000 0111 1111(補(bǔ)),補(bǔ)碼轉(zhuǎn)原碼:符號位為0,原碼與補(bǔ)碼一樣,值為127

由此可知,無符號字符類型變量整型提升后再%d輸出沒有負(fù)數(shù)

故答案為:0-255循環(huán)

總結(jié)

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • c++之解決char轉(zhuǎn)string時(shí)出現(xiàn)的亂碼問題

    c++之解決char轉(zhuǎn)string時(shí)出現(xiàn)的亂碼問題

    這篇文章主要介紹了c++之解決char轉(zhuǎn)string時(shí)出現(xiàn)的亂碼問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • 一篇文章帶你了解C語言內(nèi)存對齊

    一篇文章帶你了解C語言內(nèi)存對齊

    在單片機(jī)下使用C語言編程時(shí),內(nèi)存對齊的知識點(diǎn)必須掌握。掌握內(nèi)存對齊后,可以防止內(nèi)存碎片化,并且證明你有能力優(yōu)化內(nèi)存。嵌入式單片機(jī)開發(fā)的后階段,無非就是優(yōu)化內(nèi)存與優(yōu)化代碼執(zhí)行效率。
    2021-08-08
  • C語言的字符函數(shù)和字符串函數(shù)詳解

    C語言的字符函數(shù)和字符串函數(shù)詳解

    這篇文章主要為大家介紹了C語言的字符函數(shù)和字符串函數(shù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01
  • 基于QT實(shí)現(xiàn)自定義溫度計(jì)的示例代碼

    基于QT實(shí)現(xiàn)自定義溫度計(jì)的示例代碼

    QT原生控件沒有實(shí)現(xiàn)如儀表盤或者溫度計(jì)的控件,只好自己實(shí)現(xiàn),所以本文為大家介紹了如何利用qt實(shí)現(xiàn)自定義溫度/濕度控件,感興趣的小伙伴可以了解下
    2023-11-11
  • C語言之格式化屏幕輸出詳解

    C語言之格式化屏幕輸出詳解

    這篇文章主要介紹了C語言之格式化屏幕輸出的相關(guān)資料,需要的朋友可以參考下,小編覺得這篇文章寫的還不錯(cuò),希望能夠給你帶來幫助
    2021-11-11
  • C++實(shí)現(xiàn)簡易通訊錄功能

    C++實(shí)現(xiàn)簡易通訊錄功能

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡易通訊錄功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • C語言 掃雷程序的實(shí)現(xiàn)

    C語言 掃雷程序的實(shí)現(xiàn)

    這篇文章主要介紹了C語言 掃雷程序的實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • C語言實(shí)現(xiàn)線索二叉樹的前中后創(chuàng)建和遍歷詳解

    C語言實(shí)現(xiàn)線索二叉樹的前中后創(chuàng)建和遍歷詳解

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)線索二叉樹的前中后創(chuàng)建和遍歷,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • C語言實(shí)現(xiàn)線索二叉樹的定義與遍歷示例

    C語言實(shí)現(xiàn)線索二叉樹的定義與遍歷示例

    這篇文章主要介紹了C語言實(shí)現(xiàn)線索二叉樹的定義與遍歷,結(jié)合具體實(shí)例形式分析了基于C語言的線索二叉樹定義及遍歷操作相關(guān)實(shí)現(xiàn)技巧與注意事項(xiàng),需要的朋友可以參考下
    2017-06-06
  • C++特殊成員函數(shù)以及其生成機(jī)制詳解

    C++特殊成員函數(shù)以及其生成機(jī)制詳解

    這篇文章主要給大家介紹了關(guān)于C++特殊成員函數(shù)以及其生成機(jī)制的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-02-02

最新評論