點擊左上方藍色“一口Linux”,選擇“設為星標”
第一時間看干貨文章? ?【干貨】嵌入式驅動工程師學習路線 ?【干貨】Linux嵌入式知識點-思維導圖-免費獲取 ?【就業】一個可以寫到簡歷的基于Linux物聯網綜合項目 ?【就業】找工作簡歷模版 ?1
C語言內存分區示意圖如下:

棧區由編譯器自動分配釋放,由操作系統自動管理,無須手動管理。
棧區上的內容只在函數范圍內存在,當函數運行結束,這些內容也會自動被銷毀。
棧區按內存地址由高到低方向生長,其最大大小由編譯時確定,速度快,但自由性差,最大空間不大。
棧區是先進后出原則,即先進去的被堵在屋里的最里面,后進去的在門口,釋放的時候門口的先出去。
臨時創建的局部變量和const定義的局部變量存放在棧區。
函數調用和返回時,其入口參數和返回值存放在棧區。
堆區由程序員分配內存和釋放。
堆區按內存地址由低到高方向生長,其大小由系統內存/虛擬內存上限決定,速度較慢,但自由性大,可用空間大。
用malloc等函數實現動態分布內存。
void *malloc(size_t);參數size_t是分配的字節大小。
返回值是一個void*型的指針,該指針指向分配空間的首地址。
(void *型指針可以任意轉換為其他類型的指針)
用free函數進行內存釋放,否則會造成內存泄漏。
void free(void * /*ptr*/);參數是開辟的內存的首地址。
通常是用于那些在編譯期間就能確定存儲大小的變量的存儲區,但它用于的是在整個程序運行期間都可見的全局變量和靜態變量。
全局區有?.bss段?和?.data段組成,可讀可寫。
未初始化的全局變量和未初始化的靜態變量存放在.bss段。
初始化為0的全局變量和初始化為0的靜態變量存放在.bss段。
.bss段不占用可執行文件空間,其內容由操作系統初始化。
已初始化的全局變量存放在.data段。
已初始化的靜態變量存放在.data段。
.data段占用可執行文件空間,其內容有程序初始化。
字符串、數字等常量存放在常量區。
const修飾的全局變量存放在常量區。
程序運行期間,常量區的內容不可以被修改。
程序執行代碼存放在代碼區,其值不能修改(若修改則會出現錯誤)。
字符串常量和define定義的常量也有可能存放在代碼區。
RAM是與CPU直接交換數據的內部存儲器,也叫主存(內存)。
它可以隨時讀寫,而且速度很快,通常作為操作系統或其他正在運行中的程序的臨時數據存儲媒介。
當電源關閉時RAM不能保留數據(掉電數據消失哦)如果需要保存數據,就必須把它們寫入一個長期的存儲設備中(例如硬盤)。
ROM所存數據,一般是裝入整機前事先寫好的,整機工作過程中只能讀出,而不像隨機存儲器那樣能快速地、方便地加以改寫。
ROM所存數據穩定,斷電后所存數據也不會改變。
本文使用是STM32F103芯片,keil V5環境下默認的內存配置見下圖:

ROM區域是0x8000000開始,大小是0x10000,這片區域是只讀區域,不可修改,存放代碼區和常量區。
RAM區域是0x20000000開始,大小是0x5000,這片區域是可讀寫區域,存放的是全局(靜態)區、堆區和棧區。
該芯片的內部分區如下圖所示:

#include "main.h"
#include //用于字符串處理
#include //用于printf打印
#include //用于分配堆區---調用malloc和free
#include "delay.h"
#include "uart3.h"
#include "led.h"
//全局區
int q1; //未初始化全局變量
static int q2; //未初始化靜態變量
const int q3; //未初始化只讀變量
int m1=1; //已初始化全局變量
static int m2=2; //已初始化靜態變量
//常量區
const int m3=3; //已初始化只讀變量
int main(void)
{
SystemCoreClockUpdate(); //設置系統時鐘為72M
LED_GPIO_Config();
Uart3_init();
while(1)
{
//棧區
int mq1; //未初始化局部變量
int *mq2; //未初始化局部指針變量
int mq3=3; //已初始化局部變量
char qq[10] = "hello"; //已初始化局部數組
const int mq4; //未初始化局部只讀變量
const int mq5=3; //已初始化局部只讀變量
//堆區
int *p1 = malloc(4); //已初始化局部指針變量p1
int *p2 = malloc(4); //已初始化局部指針變量p2
//全局區
static int mp1; //未初始化局部靜態變量
static int mp2=2; //已初始化局部靜態變量
//常量區
char *vv = "I LOVE YOU";//已初始化局部指針變量
char *mq = "5201314";
printf("\n棧區-變量地址\n");
printf("未初始化局部變量 :0x%p\r\n",&mq1);
printf("未初始化局部指針變量 :0x%p\r\n",&mq2);
printf("已初始化局部變量 :0x%p\r\n",&mq3);
printf("已初始化局部數組 :0x%p\r\n", qq );
printf("未初始化局部只讀變量 :0x%p\r\n",&mq4);
printf("已初始化局部只讀變量 :0x%p\r\n",&mq5);
printf("\n堆區-動態申請地址\r\n");
printf("已初始化局部int型指針變量p1 :0x%p\r\n", p1);
printf("已初始化局部int型指針變量p2 :0x%p\r\n", p2);
printf("\n全局區-變量地址\n");
printf("未初始化全局變量 :0x%p\r\n",&q1);
printf("未初始化靜態變量 :0x%p\r\n",&q2);
printf("未初始化只讀變量 :0x%p\r\n",&q3);
printf("已初始化全局變量 :0x%p\r\n",&m1);
printf("已初始化靜態變量 :0x%p\r\n",&m2);
printf("未初始化局部靜態變量 :0x%p\r\n",&mp1);
printf("已初始化局部靜態變量 :0x%p\r\n",&mp2);
printf("\n常量區地址\n");
printf("已初始化只讀變量 :0x%p\r\n",&m3);
printf("已初始化局部指針變量 :0x%p\r\n",vv );
printf("已初始化局部指針變量 :0x%p\r\n",mq );
printf("\n代碼區地址\n");
printf("程序代碼區main函數入口地址 :0x%p\n", main);
led485_flicker();
delay_ms(1000);
free(p1);
free(p2);
}
}end
一口Linux?
關注,回復【1024】海量Linux資料贈送
精彩文章合集
文章推薦