㈠ 在c語言中,如何給函數分配內存
函數的相對地址在編譯鏈接的時候就已經分配好了,但是絕對地址是未知的。就是說,函數的地址相對於程序基址的偏移是確定的,但是程序在運行的時候,會被載入到哪一個區域運行是不確定的,需要由操作系統根據內存的使用的情況等進行調度,所以函數在內存中的絕對地址也就自然不確定了,希望可以幫到你。
㈡ 編寫C語言時使用分配內存的好處
C裡面使用自動分配內存,比如說malloc<分配自由存取區,就把它當作是在堆上分配的了>,他的好處是可分配的內存更大更靈活<理論上可以分配用戶空間能使用的所有虛擬內存空間>,它是通過鏈式分配的,比如說有這樣的一個語句
int *p=(int *)malloc(sizeof(int)),意思是,先在棧上創建一個int類型的指針變數,再在堆上分配4個位元組大小的空間<32位>,再把創建的內存首地址賦給p;
在上面這個題目中,p是在棧上分配的<就是所謂的手動分配<最多能分配的好象是1M空間的大小,有的說是2M>,正因為在堆上分配的它不可以自動回收內存,所以要顯試的調用free()來收回內存,還有就是如果p是局部變數的時候,一定要在p的作用域內調用free(),因為p是在棧上分配的,一但清棧之後<p的作用域沒了>,這個時候你要是想在其他地方調用free就沒效果了,這個就象鏈表的頭指針丟失
當你學C++的時候,研究一下new和malloc吧
㈢ c語言 分配超大內存
用文件內存映射,這樣系統就會把文件作為內存使用,文件有多大你虛擬出來的內存就有多大
㈣ 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);
}
(4)c語言分配內存擴展閱讀
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語言中分配內存的函數是怎麼寫的
Windows下的 malloc 原理就是調用 windows API 的各種內存管理函數申請內存並記錄內存狀態以便將來釋放。
DOS下的 malloc 原理就是調用申請內存的中斷申請內存並記錄內存狀態以便將來釋放。
UNIX 和 Linux 都有內存管理的系統調用,malloc 相當於給這些系統調用穿了一件
malloc()工作機制
malloc函數的實質體現在,它有一個將可用的內存塊連接為一個長長的列表的所謂空閑鏈表。調用malloc函數時,它沿連接表尋找一個大到足以滿足用戶請求所需要的內存塊。然後,將該內存塊一分為二(一塊的大小與用戶請求的大小相等,另一塊的大小就是剩下的位元組)。接下來,將分配給用戶的那塊內存傳給用戶,並將剩下的那塊(如果有的話)返回到連接表上。調用free函數時,它將用戶釋放的內存塊連接到空閑鏈上。到最後,空閑鏈會被切成很多的小內存片段,如果這時用戶申請一個大的內存片段,那麼空閑鏈上可能沒有可以滿足用戶要求的片段了。於是,malloc函數請求延時,並開始在空閑鏈上翻箱倒櫃地檢查各內存片段,對它們進行整理,將相鄰的小空閑塊合並成較大的內存塊。
malloc()在操作系統中的實現
在 C 程序中,多次使用malloc () 和 free()。不過,您可能沒有用一些時間去思考它們在您的操作系統中是如何實現的。本節將向您展示 malloc 和 free 的一個最簡化實現的代碼,來幫助說明管理內存時都涉及到了哪些事情。
在大部分操作系統中,內存分配由以下兩個簡單的函數來處理:
void *malloc (long numbytes):該函數負責分配 numbytes 大小的內存,並返回指向第一個位元組的指針。
void free(void *firstbyte):如果給定一個由先前的 malloc 返回的指針,那麼該函數會將分配的空間歸還給進程的「空閑空間」。
malloc_init 將是初始化內存分配程序的函數。它要完成以下三件事:將分配程序標識為已經初始化,找到系統中最後一個有效內存地址,然後建立起指向我們管理的內存的指針。這三個變數都是全局變數:
//清單 1. 我們的簡單分配程序的全局變數
int has_initialized = 0;
void *managed_memory_start;
void *last_valid_address;
如前所述,被映射的內存的邊界(最後一個有效地址)常被稱為系統中斷點或者 當前中斷點。在很多 UNIX? 系統中,為了指出當前系統中斷點,必須使用 sbrk(0) 函數。 sbrk 根據參數中給出的位元組數移動當前系統中斷點,然後返回新的系統中斷點。使用參數 0 只是返回當前中斷點。這里是我們的 malloc 初始化代碼,它將找到當前中斷點並初始化我們的變數:
清單 2. 分配程序初始化函數
#include
void malloc_init()
{
last_valid_address = sbrk(0);
managed_memory_start = last_valid_address;
has_initialized = 1;
}
現在,為了完全地管理內存,我們需要能夠追蹤要分配和回收哪些內存。在對內存塊進行了 free 調用之後,我們需要做的是諸如將它們標記為未被使用的等事情,並且,在調用 malloc 時,我們要能夠定位未被使用的內存塊。因此, malloc 返回的每塊內存的起始處首先要有這個結構:
//清單 3. 內存控制塊結構定義
struct mem_control_block {
int is_available;
int size;
};
現在,您可能會認為當程序調用 malloc 時這會引發問題 —— 它們如何知道這個結構?答案是它們不必知道;在返回指針之前,我們會將其移動到這個結構之後,把它隱藏起來。這使得返回的指針指向沒有用於任何其他用途的內存。那樣,從調用程序的角度來看,它們所得到的全部是空閑的、開放的內存。然後,當通過 free() 將該指針傳遞回來時,我們只需要倒退幾個內存位元組就可以再次找到這個結構。
在討論分配內存之前,我們將先討論釋放,因為它更簡單。為了釋放內存,我們必須要做的惟一一件事情就是,獲得我們給出的指針,回退 sizeof(struct mem_control_block) 個位元組,並將其標記為可用的。這里是對應的代碼:
清單 4. 解除分配函數
void free(void *firstbyte) {
struct mem_control_block *mcb;
mcb = firstbyte - sizeof(struct mem_control_block);
mcb->is_available = 1;
return;
}
如您所見,在這個分配程序中,內存的釋放使用了一個非常簡單的機制,在固定時間內完成內存釋放。分配內存稍微困難一些。我們主要使用連接的指針遍歷內存來尋找開放的內存塊。這里是代碼:
//清單 6. 主分配程序
void *malloc(long numbytes) {
void *current_location;
struct mem_control_block *current_location_mcb;
void *memory_location;
if(! has_initialized) {
malloc_init();
}
numbytes = numbytes + sizeof(struct mem_control_block);
memory_location = 0;
current_location = managed_memory_start;
while(current_location != last_valid_address)
{
current_location_mcb =
(struct mem_control_block *)current_location;
if(current_location_mcb->is_available)
{
if(current_location_mcb->size >= numbytes)
{
current_location_mcb->is_available = 0;
memory_location = current_location;
break;
}
}
current_location = current_location +
current_location_mcb->size;
}
if(! memory_location)
{
sbrk(numbytes);
memory_location = last_valid_address;
last_valid_address = last_valid_address + numbytes;
current_location_mcb = memory_location;
current_location_mcb->is_available = 0;
current_location_mcb->size = numbytes;
}
memory_location = memory_location + sizeof(struct mem_control_block);
return memory_location;
}
這就是我們的內存管理器。現在,我們只需要構建它,並在程序中使用它即可.多次調用malloc()後空閑內存被切成很多的小內存片段,這就使得用戶在申請內存使用時,由於找不到足夠大的內存空間,malloc()需要進行內存整理,使得函數的性能越來越低。聰明的程序員通過總是分配大小為2的冪的內存塊,而最大限度地降低潛在的malloc性能喪失。也就是說,所分配的內存塊大小為4位元組、8位元組、16位元組、 18446744073709551616位元組,等等。這樣做最大限度地減少了進入空閑鏈的怪異片段(各種尺寸的小片段都有)的數量。盡管看起來這好像浪費了空間,但也容易看出浪費的空間永遠不會超過50%。
㈥ c語言寫的一個程序,在運行,內存是怎麼分配的
在線等?幾天了?
還是先回答問題吧,c語言運行時分配內存是用malloc()函數,它是向操作系統提出內存申請,然後由操作系統完成內存的分配,最後把分配的內存的首地址返回給程序。例如,我想申請一個4位元組的內存,我就void *p=malloc(4);
釋放不用的內存就用free,例如釋放上面的那4位元組,我就free(p);
就是這樣子。
㈦ 關於c語言程序內存分配的問題
比如: for ( ;; ) { int a; }
這個臨時變數a分配是在棧中,如果是malloc是在堆中。
一般來說,c語言大括弧中開設的變數,除主程序的外都是在棧中,malloc都是在堆中。
㈧ c語言內存有幾種分配方式
基本上C程序的元素存儲在內存的時候有3種分配策略:
靜態分配
如果一個變數聲明為全局變數或者是函數的靜態變數,這個變數的存儲將使用靜態分配方式。靜態分配的內存一般會被編譯器放在數據段或代碼段來存儲,具體取決於實現。這樣做的前提是,在編譯時就必須確定變數的大小。 以IA32的x86平台及gcc編譯器為例,全局及靜態變數放在數據段的低端;全局及靜態常量放在代碼段的高端
自動分配
函數的自動局部變數應該隨著函數的返回會自動釋放(失效),這個要求在一般的體系中都是利用棧(Stack)來滿足的。相比於靜態分配,這時候,就不必絕對要求這個變數在編譯時就必須確定變數的大小,運行時才決定也不遲,但是C89仍然要求在編譯時就要確定,而C99放鬆了這個限制。但無論是C89還是C99,都不允許一個已經分配的自動變數運行時改變大小。
所以說C函數永遠不應該返回一個局部變數的地址。
要指出的是,自動分配也屬於動態分配,甚至可以用alloca函數來像分配堆(Heap)一樣進行分配,而且釋放是自動的。
動態分配
還有一種更加特殊的情況,變數的大小在運行時有可能改變,或者雖然單個變數大小不變,變數的數目卻有很大彈性,不能靜態分配或者自動分配,這時候可以使用堆(Heap)來滿足要求。ANSI C定義的堆操作函數是malloc、calloc、realloc和free。
使用堆(Heap)內存將帶來額外的開銷和風險。
㈨ C語言中分配內存
要實現根據程序的需要動態分配存儲空間,就必須用到以下幾個函數
1、malloc函數
malloc函數的原型為:
void
*malloc
(u
igned
int
size)
其作用是在內存的動態存儲區中分配一個長度為size的連續空間。其參數是一個無符號整形數,返回值是一個指向所分配的連續存儲域的起始地址的指針。還有一點必須注意的是,當函數未能成功分配存儲空間(如內存不足)就會返回一個NULL指針。所以在調用該函數時應該檢測返回值是否為NULL並執行相應的操作。
下例是一個動態分配的程序:
#include
#include
main()
{
int
count,*array;
/*count是一個計數器,array是一個整型指針,也可以理解為指向一個整型數組的首地址*/
if((array(int
*)
malloc(10*sizeof(int)))==NULL)
{
printf("不能成功分配存儲空間。");
exit(1);
}
for
(count=0;count〈10;count++)
/*給數組賦值*/
array[count]=count;
for(count=0;count〈10;count++)
/*列印數組元素*/
printf("%2d",array[count]);
}
上例中動態分配了10個整型存儲區域,然後進行賦值並列印。例中if((array(int
*)
malloc(10*sizeof(int)))==NULL)語句可以分為以下幾步:
1)分配10個整型的連續存儲空間,並返回一個指向其起始地址的整型指針
2)把此整型指針地址賦給array
3)檢測返回值是否為NULL
2、free函數
由於內存區域總是有限的,不能不限制地分配下去,而且一個程序要盡量節省資源,所以當所分配的內存區域不用時,就要釋放它,以便其它的變數或者程序使用。這時我們就要用到free函數。
其函數原型是:
void
free(void
*p)
作用是釋放指針p所指向的內存區。
其參數p必須是先前調用malloc函數或calloc函數(另一個動態分配存儲區域的函數)時返回的指針。給free函數傳遞其它的值很可能造成死機或其它災難性的後果。
注意:這里重要的是指針的值,而不是用來申請動態內存的指針本身。例:
int
*p1,*p2;
p1=malloc(10*sizeof(int));
p2=p1;
……
free(p2)
/*或者free(p2)*/
malloc返回值賦給p1,又把p1的值賦給p2,所以此時p1,p2都可作為free函數的參數。
malloc函數是對存儲區域進行分配的。
free函數是釋放已經不用的內存區域的。
所以由這兩個函數就可以實現對內存區域進行動態分配並進行簡單的管理了。
㈩ C語言如何給指針分配內存
1, 找到VS的cl.exe所在目錄,把這目錄復制下來:
我的VS2008的CL.EXE目錄是在E:\Program Files\Microsoft Visual Studio 9.0\VC\bin,
VS2010可以類似的找到..
在'我的電腦'上點右鍵,
選右鍵菜單'屬性'->'高級'->'環境變數',
在彈出的環境變數設置框里找"PATH"這個變數, (在用戶變數或系統變數里都可以)
然後在"PATH"的值後面,用分號分隔,
把將才找到的路徑串復制進去,選確定.
2, 重新運行CMD開啟新的命令窗.
3, 輸入cl回車檢查PATH路徑是否生效.
//以上步聚是設置環境變數,只需設一次以後就好用了.以後每次要命令行下編譯C++程序,就從下面第4步開始.
4, 輸入vcvars32 ,運行cl.exe同一路徑下的vcvars32.bat,設置其它環境變數.
5, 寫一個helloworld程序,保存成hello.cpp, cl hello.cpp回車試試編譯正常不. 如果成功,則生成hello.exe文件.
//-----------------------------------------------------------
C/C++ 編譯器選項
-優化-
/O1 最小化空間 /Op[-] 改善浮點數一致性
/O2 最大化速度 /Os 優選代碼空間
/Oa 假設沒有別名 /Ot 優選代碼速度
/Ob<n> 內聯展開(默認 n=0) /Ow 假設交叉函數別名
/Od 禁用優化(默認值) /Ox 最大化選項。(/Ogityb2 /Gs)
/Og 啟用全局優化 /Oy[-] 啟用框架指針省略
/Oi 啟用內部函數
-代碼生成-
/G3 為 80386 進行優化 /Gh 啟用 _penter 函數調用
/G4 為 80486 進行優化 /GH 啟用 _pexit 函數調用
/G5 為 Pentium 進行優化 /GR[-] 啟用 C++ RTTI
/G6 對 PPro、P-II、P-III 進行優化 /GX[-] 啟用 C++ EH (與 /EHsc 相同)
/G7 對 Pentium 4 或 Athlon 進行優化 /EHs 啟用 C++ EH (沒有 SEH 異常)
/GB 為混合模型進行優化(默認) /EHa 啟用 C++ EH(w/ SEH 異常)
/Gd __cdecl 調用約定 /EHc extern "C" 默認為 nothrow
/Gr __fastcall 調用約定 /GT 生成纖維安全 TLS 訪問
/Gz __stdcall 調用約定 /Gm[-] 啟用最小重新生成
/GA 為 Windows 應用程序進行優化 /GL[-] 啟用鏈接時代碼生成
/Gf 啟用字元串池 /QIfdiv[-] 啟用 Pentium FDIV 修復
/GF 啟用只讀字元串池 /QI0f[-] 啟用 Pentium 0x0f 修復
/Gy 分隔鏈接器函數 /QIfist[-] 使用 FIST 而不是 ftol()
/GZ 啟用堆棧檢查(/RTCs) /RTC1 啟用快速檢查(/RTCsu)
/Ge 對所有函數強制堆棧檢查 /RTCc 轉換為較小的類型檢查
/Gs[num] 控制堆棧檢查調用 /RTCs 堆棧幀運行時檢查
/GS 啟用安全檢查 /RTCu 未初始化的本地用法檢查
/clr[:noAssembly] 為公共語言運行庫編譯
noAssembly - 不產生程序集
/arch:<SSE|SSE2> CPU 結構的最低要求,以下內容之一:
SSE - 啟用支持 SSE 的 CPU 可用的指令
SSE2 - 啟用支持 SSE2 的 CPU 可用的指令
-輸出文件-
/Fa[file] 命名程序集列表文件 /Fo<file> 命名對象文件
/FA[sc] 配置程序集列表 /Fp<file> 命名預編譯頭文件
/Fd[file] 命名 .PDB 文件 /Fr[file] 命名源瀏覽器文件
/Fe<file> 命名可執行文件 /FR[file] 命名擴展 .SBR 文件
/Fm[file] 命名映射文件
-預處理器-
/AI<dir> 添加到程序集搜索路徑 /Fx 將插入的代碼合並到文件
/FU<file> 強制使用程序集/模塊 /FI<file> 命名強制包含文件
/C 不抽出注釋 /U<name> 移除預定義宏
/D<name><text> 定義宏 /u 移除所有預定義宏
/E 預處理到 stdout /I<dir> 添加到包含搜索路徑
/EP 預處理到 stdout,沒有 #line /X 忽略「標准位置」
/P 預處理到文件
-語言-
/Zi 啟用調試信息 /Ze 啟用擴展(默認)
/ZI 啟用「編輯並繼續」調試信息 /Zl 省略 .OBJ 中的默認庫名
/Z7 啟用舊式調試信息 /Zg 生成函數原型
/Zd 僅有行號調試信息 /Zs 只進行語法檢查
/Zp[n] 在 n 位元組邊界上包裝結構 /vd 禁用/啟用 vtordisp
/Za 禁用擴展(暗指 /Op) /vm<x> 指向成員的指針類型
/Zc:arg1[,arg2] C++ 語言一致性,這里的參數可以是:
forScope - 對范圍規則強制使用標准 C++
wchar_t - wchar_t 是本機類型,不是 typedef
- 雜項 -
@<file> 選項響應文件 /wo<n> 發出一次警告 n
/?, /help 列印此幫助消息 /w<l><n> 為 n 設置警告等級 1-4
/c 只編譯,不鏈接 /W<n> 設置警告等級(默認 n=1)
/H<num> 最大外部名稱長度 /Wall 啟用所有警告
/J 默認 char 類型是 unsigned /Wp64 啟用 64 位埠定位警告
/nologo 取消顯示版權消息 /WX 將警告視為錯誤
/showIncludes 顯示包含文件名 /WL 啟用單行診斷
/Tc<source file> 將文件編譯為 .c /Yc[file] 創建 .PCH 文件
/Tp<source file> 將文件編譯為 .cpp /Yd 將調試信息放在每個 .OBJ 中
/TC 將所有文件編譯為 .c /Yl[sym] 為調試庫插入 .PCH 引用
/TP 將所有文件編譯為 .cpp /Yu[file] 使用 .PCH 文件
/V<string> 設置版本字元串 /YX[file] 自動 .PCH
/w 禁用所有警告 /Y- 禁用所有 PCH 選項
/wd<n> 禁用警告 n /Zm<n> 最大內存分配(默認為 %)
/we<n> 將警告 n 視為錯誤
-鏈接-
/MD 與 MSVCRT.LIB 鏈接 /MDd 與 MSVCRTD.LIB 調試庫鏈接
/ML 與 LIBC.LIB 鏈接 /MLd 與 LIBCD.LIB 調試庫鏈接
/MT 與 LIBCMT.LIB 鏈接 /MTd 與 LIBCMTD.LIB 調試庫鏈接
/LD 創建 .DLL /F<num> 設置堆棧大小
/LDd 創建 .DLL 調試庫 /link [鏈接器選項和庫]
如果對您有幫助,請記得採納為滿意答案,謝謝!祝您生活愉快!