??:如果你也對機(jī)器人、人工智能感興趣,看來我們志同道合?
??:不妨瀏覽一下我的博客主頁【https://blog.csdn.net/weixin_51244852】
??:文章若有幸對你有幫助,可點(diǎn)贊 ?? 收藏 ?不迷路??
??:內(nèi)容若有錯(cuò)誤,敬請留言 ??指正!原創(chuàng)文,轉(zhuǎn)載請注明出處
前言:
??C語言語句的本質(zhì)是什么?
以下面的代碼為例結(jié)合內(nèi)存來解析語句的本質(zhì),其實(shí)跟內(nèi)存地址密切相關(guān)。
int a; // 編譯器申請了1個(gè)int類型的內(nèi)存格子
//格子的長度是4字節(jié),地址是確定的,但只有編譯器知道并把符號(hào)a和這個(gè)格子綁定在一起。
a = 5; // 編譯器會(huì)把5放入符號(hào)a綁定的內(nèi)存格子中。
a += 4; // 編譯器先把a(bǔ)原來的值讀出來,然后給這個(gè)值加4,再把加之后的和賦值給a。
??數(shù)據(jù)類型的本質(zhì)是什么?
不管是普通變量類型,還是指針類型等,只要記?。?br> 類型只是對后面數(shù)字或者符號(hào)(代表的是內(nèi)存地址)所表征的內(nèi)存的一種長度規(guī)定和解析方法的規(guī)定而已。
一、內(nèi)存操作方式
1.1指針間接訪問內(nèi)存
C語言中的指針,全名叫指針變量,指針變量其實(shí)很普通變量沒有任何區(qū)別。
??譬如:
int a和int *p其實(shí)沒有任何區(qū)別,a和p都代表一個(gè)內(nèi)存地址,假設(shè)是0x30000000,但是他們對這個(gè)內(nèi)存地址的長度和解析方法不同的:
??a是int型,所以a的長度是4字節(jié),解析方法是按照int的規(guī)定來;
??p是int *類型,所以長度是4字節(jié),解析方法是int *的規(guī)定來(0x30000000開頭的連續(xù)4字節(jié)中存儲(chǔ)了1個(gè)地址,這個(gè)地址所代表的內(nèi)存單元中存放的是一個(gè)int類型的數(shù))。
??:因此,普通變量、數(shù)組、指針變量其實(shí)都沒有本質(zhì)差別,都是對內(nèi)存地址的解析,只是解析方法不一樣。
1.2數(shù)組管理內(nèi)存
數(shù)組管理內(nèi)存同樣和變量無本質(zhì)差別,僅僅是對符號(hào)解析方法的不同。
??例如:
int a;//編譯器分配4字節(jié)長度給a,并且把首地址和符號(hào)a綁定起來。
int b[10]; //編譯器分配40個(gè)字節(jié)長度給b,并且把首元素首地址和符號(hào)b綁定。
數(shù)組中第一個(gè)元素(a[0])為首元素;每一個(gè)元素類型都是int,所以長度都是4,其中第一個(gè)字節(jié)的地址就稱為首地址;首元素a[0]的首地址就稱為首元素首地址。
1.3內(nèi)存管理之棧
??什么是棧?
棧(stack)是一種數(shù)據(jù)結(jié)構(gòu),用于管理內(nèi)存。C語言中使用棧來保存局部變量。
??棧管理內(nèi)存的特點(diǎn):
1、小內(nèi)存、自動(dòng)化
2、先進(jìn)后出(first in last out,F(xiàn)ILO)
棧的特點(diǎn)是入口即出口,只有一個(gè)口,另一個(gè)口是堵死的。所以先進(jìn)去的必須后出來,類似彈匣的原理。
反之,隊(duì)列的特點(diǎn)是入口和出口都有,必須從入口進(jìn)去,從出口出來,所以先進(jìn)去的必須先出來,否則就堵住后面的。先進(jìn)先出( first in first out ,F(xiàn)IFO)隊(duì)列
3、預(yù)定棧的大小不靈活,怕溢出
首先,棧是有大小,所以棧內(nèi)存大小不好設(shè)置。如果太小怕溢出,太大怕浪費(fèi)內(nèi)存,與數(shù)組類似
其次,棧的溢出危害很大,一定要避免。因此不能定義太多或者太大的局部變量時(shí),比如:不能定義 int b[20000]。
1.4內(nèi)存管理之堆
??什么是堆?
“堆”(Heap)是一種數(shù)據(jù)結(jié)構(gòu),用于動(dòng)態(tài)分配內(nèi)存空間。堆內(nèi)存分配由程序員手動(dòng)控制,它與靜態(tài)分配的棧內(nèi)存不同。
??堆管理內(nèi)存的特點(diǎn):
1、用于管理大塊內(nèi)存
容量不限(常規(guī)使用的需求容量都能滿足)
2、手工分配&使用&釋放
申請及釋放都需要手工進(jìn)行,即需要程序員寫代碼明確進(jìn)行申請malloc及釋放free。
3、容易內(nèi)存泄漏
如果申請了內(nèi)存,但使用后未釋放,會(huì)導(dǎo)致內(nèi)存丟失,也稱為內(nèi)存泄漏。
在C/C++語言中,內(nèi)存泄漏是最嚴(yán)重的程序bug,這也是大家認(rèn)為Java/C#等語言比C/C++優(yōu)秀的地方。
4、將堆內(nèi)存管理比喻成一個(gè)倉庫
倉庫管理:堆內(nèi)存需要進(jìn)行管理,就像倉庫需要管理存儲(chǔ)的物品一樣。程序員通過調(diào)用分配函數(shù)(比如malloc()或new)來向堆申請一定大小的新內(nèi)存塊,這可以類比為在倉庫中存放新的物品。同樣地,釋放函數(shù)(比如free()或delete)會(huì)將不再需要的內(nèi)存塊歸還給堆,類似于從倉庫中取出不再需要的物品。
??什么時(shí)候使用堆內(nèi)存?
需要內(nèi)存容量比較大時(shí),要求反復(fù)使用及釋放時(shí),很多數(shù)據(jù)結(jié)構(gòu)(譬如鏈表)的實(shí)現(xiàn)都要使用堆內(nèi)存。
??C語言操作堆內(nèi)存的接口(malloc和free)
堆內(nèi)存釋放時(shí)最簡單,直接調(diào)用free釋放即可。void free(void *ptr);
堆內(nèi)存申請時(shí),有3個(gè)可選擇的類似功能的函數(shù):malloc, calloc, realloc
void *malloc(size_t size);
void *calloc(size_t nmemb, size_t size);
// nmemb個(gè)單元,每個(gè)單元size字節(jié)
> void *realloc(void *ptr, size_t size);
> //改變原來申請的空間的大小的
??譬如要申請10個(gè)int元素的內(nèi)存:
malloc(40); malloc(10*sizeof(int));
calloc(10, 4); calloc(10, sizeof(int));
數(shù)組定義時(shí)必須同時(shí)給出數(shù)組元素個(gè)數(shù)(數(shù)組大?。?,而且一旦定義再無法更改。在Java等高級(jí)語言中,有一些語法技巧可以更改數(shù)組大小,但其實(shí)這只是一種障眼法。它的工作原理是:先重新創(chuàng)建一個(gè)新的數(shù)組大小為要更改后的數(shù)組,然后將原數(shù)組的所有元素復(fù)制進(jìn)新的數(shù)組,然后釋放掉原數(shù)組,最后返回新的數(shù)組給用戶;
堆內(nèi)存申請時(shí)必須給定大小,然后一旦申請完成大小不變,如果要變只能通過realloc接口。realloc的實(shí)現(xiàn)原理類似于上面說的Java中的可變大小的數(shù)組的方式。
#include <stdio.h>
#include "test.h"
int main() {
T_Size* Ming = (T_Size*)malloc(sizeof(T_Size));
if (Ming == NULL) {
printf("內(nèi)存分配失敗\n");
return -1;
}
Ming->m_bWeigth = 75;
Ming->m_wHeigth = 180;
printf("升高和體重分別為%d,%d", Ming->m_wHeigth, Ming->m_bWeigth);
free(Ming); // 釋放動(dòng)態(tài)分配的內(nèi)存
return 0;
}
總結(jié):
??堆的優(yōu)勢和劣勢
優(yōu)勢:靈活;
劣勢:需要程序員去處理各種細(xì)節(jié),所以容易出錯(cuò),嚴(yán)重依賴于程序員的水平。文章來源:http://www.zghlxwxcb.cn/news/detail-704924.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-704924.html
到了這里,關(guān)于【C語言練習(xí)】C語言如何操作內(nèi)存(重中之重?。。。┑奈恼戮徒榻B完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!