c語言4個區
Ⅰ c語言數組在內存中是怎麼分配的
C語言中內存為分三類:棧區、堆區、靜態數據區。
局部變數在棧上分配,函數調用前的棧指針,要和函數返回後的棧指針一樣,否則就會出錯。
void test(void)
{
char i,a[10];
printf("0x%x", &i);
printf("0x%x", a);
printf("0x%x", a+1);
printf("0x%x", a+2);
printf("0x%x", a+3);
}
(1)c語言4個區擴展閱讀
c語言數組在內存分配
示例:
#include<stdio.h>
int main()
{
int a[4] = {11,12,13,14};
int b[4] = {21,22,23,24};
int *pa = &a;
int i = 0;
while(i<8)
{
i++;
printf("now *p value = %d and",*pa);
printf("p addr value = %d ",pa);
pa++;
}
return 0;
}
Ⅱ C語言運行的內存要求是哪三個是不是程序代碼區,靜態存儲區和動態存儲區。求高人路過
一個由c/C++編譯的程序佔用的內存分為以下幾個部分
1、棧區(stack)— 由編譯器自動分配釋放 ,存放函數的參數值,局部變數的值等。其操作方式類似於數據結構中的棧。2、堆區(heap) — 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收 。注意它與數據結構中的堆是兩回事,分配方式倒是類似於鏈表,呵呵。3、全局區(靜態區)(static)—,全局變數和靜態變數的存儲是放在一塊的,初始化的全局變數和靜態變數在一塊區域, 未初始化的全局變數和未初始化的靜態變數在相鄰的另一塊區域。 - 程序結束後有系統釋放 4、文字常量區—常量字元串就是放在這里的。 程序結束後由系統釋放5、程序代碼區—存放函數體的二進制代碼。
Ⅲ C語言代碼組成 - BSS、Data、Stack、Heap、Code、Const
一段C語言經過編譯連接後,成為一段可以運行的代碼,可運行的代碼可以分為以下四個部分組成:全局變數/靜態變數區、堆、棧、代碼區。其中全局變數/靜態變數區又分為未初始化變數區和初始化變數區,代碼區又分為代碼和常量區。即匯總下來,代碼可以分為6部分組成,包括:BSS區(未初始化的全局變數/靜態變數區)、Data區(實始化的全局變數區)、Stack區(棧區)、heap區(堆區)、Code區(代碼區)、const區(常量區)。
一、BSS區和Data區
C語言編程中定義的全局變數、靜態局部變數,就是分配在全局變數/靜態變數區域,但是為什麼又要分為BSS區域和Data區域呢?其實我們在定義全局或者靜態變數區,有時我會對它賦初始值,有的又不會賦初始化,比如我們定義的全局變數,初始化的賦值,是怎麼樣寫到變數區域中的,我們定義的靜態局部變數,在定義時初始化後,為什麼後面函數被調用,又不會再初始化呢?這個局部靜態變數是怎麼樣實始化的,什麼時候初始化的?
如果分析編譯後的匯編代碼,就會發現在代碼運行起來後,會有一段給變數賦值的指令,這一段代碼,不是我們C代碼對應的匯編,而是C編譯器生成的匯編譯代碼,這段代碼的作用就是給初始化了的靜態變數和全局變數進行初始化。這也是為什麼全局/靜態變數區域,要分BSS和Data的原因。
二、Stack區
棧是一種先進後出的數據結構,這種數據結構正好完美的匹配函數調用時的模型過程,比如函數f(a)在運行過程中調用函數f(b),f(a)在運行過程中的變數就是分配在棧中,通過在調用f(b)前,會將代碼中用到的R0~Rn寄存器的值保存到棧中,同時將函數的傳入參數寫入到棧中,然後進入f(b)函數,函數f(b)的變數b分配在棧中,當函數運行完畢後,釋放變數b,將棧中存放的f(a)函數的運行的R0~Rn寄存器值恢復到寄存器中,同時f(b)的返回結果存入到棧中,這樣f(a)繼續運行。當一個函數運行完畢後,它在棧中分配的臨時變數會全部釋放。
對於中斷也是一樣的,中斷發生時,也是一個函數打斷了另一個函數的運行,這種現場的保存(即寄存器的值),都是通過棧來完成的。所以棧的作用有:
三、Heap區
全局變數分配的內存在代碼整個運行周期內都是有效的,而在棧區分配的內存在函數調用完成後,就會釋放。這兩種內存模型都是由編譯器決定它的使用,代碼是無法控制的。那有沒有內存是由用戶控制的,要用時,就自由分配,不用時,就自行釋放?答案是肯定的,這部分內存就是堆。
用戶需要使用的動態內存,就是通過malloc函數,調用分配的,在沒有釋放前,可一直由代碼使用。當這部分內存不再需要使用時,可以通過free函數進行釋放,將它歸還到堆中。從這中可以看出,堆的內存,是按需分配的。這就是賦予了代碼很大的自由度,但這也是會帶來負作用的,比如:內存碎片化導致的malloc失敗;忘記釋放內存導致的內存泄露,而這些往往是致命的失誤。
四、Code區
代碼區就是編譯後機器指令,這些指令決定了功能的執行。我們編譯的代碼一般是下載進flash中,但是運行,卻有兩種方式:在RAM中運行和在ROM中運行。 在RAM中運行,即是boot啟動後,將flash中的代碼復制到RAM中,然後PC指針在指到RAM中的代碼中開始運行。 有時在調試時,我們可以直接將代碼下載進RAM中運行進行調試,這樣加快調試速度。便是大部分的情況我們的代碼是從flash中開始運行的。
五、常量區
代碼中的常量,一部分是作為立即數,在代碼區中,但是像定義的字元串、給某數組賦值的一串數值,這些常量,就存在常量區,我們常用const來定義一個常量,即該變數不能再必變。這部分的變數,編譯器一般將它定義的flash中。
六、各個區域大小的是如何決定的:
code區和const區:是由代碼的大小和代碼中常量的多少來決定的。
bss區和data區:這是由代碼中定義的全局變數和局部變數的多少來決定的。
stack區:這個可以由使用都自行定義大小,但使用都要根據自已代碼的情況,評估出一個合理的值,再定義其大小,如果定義的太小,很容易爆棧,導至代碼異常,但是如果定義的太大,就容易浪費內存。
heap區:RAM剩下的部分,編譯器就會作為堆區使用。
七、嵌入式代碼一般啟動過程
以STM32為例,通過分析其匯編啟支代碼,大致可以分為以下幾個步驟:
如果大家想看編譯扣,代碼文件的組成,可以查看統後生的map文件,裡面有詳細的數據,包括各個函數的分配內存,BSS,Data,Stack,Heap,Text的分配情況。
如果相要了解詳細的代碼啟動過程,可看它的啟動匯編文件。
Ⅳ c語言數組在內存中是怎麼分配的
C語言使用的內存是虛擬內存。按照功能的不同在C語言中又將虛擬內存為分三類:棧區、堆區、靜態數據區,不管是單一變數還是數組,其內存分配都是這樣分的。
在棧區、靜態數據區、堆區會有編譯器負責分配、操作系統負責管理,程序員可以在堆區使用malloc()來動態分配堆內存的問題。
(4)c語言4個區擴展閱讀
內存的分配和釋放注意事項:
1、malloc和free是庫函數,不是系統調用
2、malloc實際分配的內存可能會比請求的多---有些編譯器分配時是以4位元組為單元的
3、不能依賴於不同平台的下的malloc
4、當請求的動態內存無法滿足時malloc返回的是NULL
5、當free的參數為NULL時,函數直接返回
Ⅳ 關於C語言變數和數組的聲明問題
首先聲明變數了是有內存分配的。
如果定義數組後可以得到連續的內存分配(有時候特別佔用空間)。所以C語言出了鏈表(可以不連續的村一組數據)。
下面是C語言內存分配特性,可以參考。
1、C中內存分為四個區
棧:用來存放函數的形參和函數內的局部變數。由編譯器分配空間,在函數執行完後由編譯器自動釋放。
堆:用來存放由動態分配函數(如malloc)分配的空間。是由程序員自己手動分配的,並且必須由程序員使用free釋放。如果忘記用free釋放,會導致所分配的空間一直占著不放,導致內存泄露。
全局局:用來存放全局變數和靜態變數。存在於程序的整個運行期間,是由編譯器分配和釋放的。
文字常量區:例如char *c = 「123456」;則」123456」為文字常量,存放於文字常量區。也由編譯器控制分配和釋放。
程序代碼區:用來存放程序的二進制代碼。
例子(一)
int a = 0; //全局區
void main()
{
int b; //棧
char s[] = abc; //s在棧,abc在文字常量區
char *p1,*p2; //棧
char *p3 = 123456; //123456在常量區,p3在棧上
static int c =0; //全局區
p1 = (char *)malloc(10); //p1在棧,分配的10位元組在堆
p2 = (char *)malloc(20); //p2在棧,分配的20位元組在堆
strcpy(p1, 123456); //123456放在常量區
}
例子(二)
//返回char型指針
char *f()
{
//s數組存放於棧上
char s[4] = {'1','2','3','0'};
return s; //返回s數組的地址,但程序運行完s數組就被釋放了
}
void main()
{
char *s;
s = f();
printf (%s, s); //列印出來亂碼。因為s所指向地址已經沒有數據
}
2、動態分配釋放內存
用malloc動態分配內存後一定要判斷一下分配是否成功,判斷指針的值是否為NULL。
內存分配成功後要對內存單元進行初始化。
內存分配成功且初始化後使用時別越界了。
內存使用完後要用free(p)釋放,注意,釋放後,p的值是不會變的,仍然是一個地址值,仍然指向那塊內存區,只是這塊內存區的值變成垃圾了。為了防止後面繼續使用這塊內存,應在free(p)後,立即p=NULL,這樣後面如果要使用,判斷p是否為NULL時就會判斷出來。
NO.1
void GetMemory(char *p)
{
p = (char *)malloc(100);
}
void Test(void)
{
char *str = NULL;
GetMemory(str);
strcpy(str,hello world);
printf(str);
}
請問運行Test函數後會是什麼樣的結果?
NO.2
char *GetMemory(void)
{
char p[] = hello world;
retrun p;
}
void Test(void)
{
char *str = NULL;
str = GetMemory();
printf(str);
}
問題同NO.1
NO.3
void GetMemory2(char **p, int num)
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str,100);
strcpy(str,hello);
printf(str);
}
問題同NO.1
NO.4
void Test(void)
{
char *str = (char *)malloc(100);
strcpy(str,hello);
free(str);
if(str != NULL)
{
strcpy(str,world);
printf(str);
}
}
問題同NO.1
我對以上問題的分析:
NO.1:程序首先申請一個char類型的指針str,並把str指向NULL(即str里存的是NULL的地址,*str為NULL中的值為0),調用函數的過程中做了如下動作:1申請一個char類型的指針p,2把str的內容到了p里(這是參數傳遞過程中系統所做的),3為p指針申請了100個空間,4返回Test函數.最後程序把字元串helloworld拷貝到str指向的內存空間里.到這里錯誤出現了!str的空間始終為NULL而並沒有實際的空間.深刻理解函數調用的第2步,將不難發現問題所在!(建議:畫圖理解)
NO.2:程序首先申請一個char類型的指針str,並把str指向NULL.調用函數的過程中做了如下動作:1申請一數組p[]並將其賦值為hello world(數組的空間大小為12),2返回數組名p付給str指針(即返回了數組的首地址).那麼這樣就可以列印出字元串"helloworld"了么?當然是不能的!因為在函數調用的時候漏掉了最後一步.也就是在第2步return數組名後,函數調用還要進行一步操作,也就是釋放內存空間.當一個函數被調用結束後它會釋放掉它裡面所有的變數所佔用的空間.所以數組空間被釋放掉了,也就是說str所指向的內容將不確定是什麼東西.
NO.3:正確答案為可以列印出hello.但內存泄漏了!
NO.4:申請空間,拷貝字元串,釋放空間.前三步操作都沒有任何問題.到if語句里的判斷條件開始出錯了,因為一個指針被釋放之後其內容並不是NULL,而是一個不確定的值.所以if語句永遠都不能被執行.這也是著名的"野"指針問題.所以我們在編寫程序釋放一個指針之後一定要人為的將指針付成NULL.這樣就會避免出現"野"指針的出現.有人說"野"指針很可怕,會帶來意想不到的錯誤.
Ⅵ C語言:內存分配---棧區、堆區、全局區、常量區和代碼區
C語言中,內存被劃分為多個區域,包括棧區、堆區、全局(靜態)區、常量區和代碼區。棧區主要存放函數調用時的局部變數,存儲速度快但空間有限。堆區用於動態分配內存,空間充足但訪問速度較慢。全局(靜態)區分為.bss段和.data段,分別存放未初始化和初始化全局變數。常量區存儲常量和字元串常量,其內容在整個程序運行期間保持不變。代碼區存放編譯後的機器指令。在STM32晶元上,內存被進一步劃分為隨機存儲器RAM和只讀存儲器ROM。RAM用於運行程序的臨時數據存儲,而ROM則用於存儲固定程序代碼。
STM32F103晶元在keil V5環境下的內存配置示意圖如下。該晶元的內存被劃分成多個區域,包括RAM、ROM、EEPROM、寄存器等,具體配置如下圖所示。
為了驗證基於STM32的代碼,以下是一個詳細的代碼示例。完整代碼可以通過以下方式免費獲取。
我們提供了一套全面的嵌入式物聯網學習資源,包含150多G的內容,覆蓋了嵌入式物聯網學習的所有關鍵領域。點擊下方鏈接,即可免費獲取這份資源。記得點贊、關注、收藏和轉發,以便與更多學習者分享。
點擊這里獲取學習資源: 掃碼進群領資料
Ⅶ C語言里,哪些變數是存放在堆里,哪些是存放在棧里
放在堆里的數據是管理員自己開辟空間和釋放空間,如,new 和malloc。
而放在棧里的數據時計算機自動分配內存和釋放的,如變數。