<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ### 內存中的數據 **程序歸根到底還是數據,當執行程序時,數據加載到內存,程序結束后,數據從內存中釋放。數據在內存中的存放共分為以下6種形式** - 程序代碼區---存放程序編譯后的可執行代碼(二進制代碼) - 全局區(靜態區)---全局變量和靜態變量的存儲室放在一塊的,初始化的全局變量和初始化的靜態變量在同一區域,未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域,程序結束后由系統釋放 - 常量區---常量就是存放在這里的,程序結束后由系統釋放 - 堆區---一般由程序員分配和釋放,如果程序員不釋放,則出現結束時可能由操作系統回收(程序不正常結束則無法回收) - 棧區---由編譯器自動分配且釋放,該區域一般存放函數的參數、局部變量 - 寄存器---內存階層的最頂端,一個有限容量的高速存放區,直接建立在中央處理器內部,用來暫存指令,數據和地址,一般用來保存棧頂指針、指令指針和現在正在被運行的指令。由于寄存器區其實是在中央處理器內部建立,而不是內存中,因此嚴格上講,不能將其劃分到內存中,只是它與內存的功能大致相同,都用來暫存數據,所以將其劃分到這里。 ### 堆棧概念 靜態內存分配 動態內存分配 * 棧內存 * 系統自動分配 * 系統自動銷毀 * 連續的內存區域 * 向低地址擴展 * 大小固定(如果申請的內存空間超過棧的剩余空間,系統會提示棧溢出,因此不要指望棧能存儲比較多的數據) * 棧上分配的內存稱為靜態內存 * 棧中的數據執行速度很快 > **棧頂的地址和棧的最大容量是由系統預先設定好的,因此棧的大小是固定的** * 靜態內存分配 * 子函數執行完,子函數中的所有局部變量都會被銷毀,內存釋放,但內存地址不可能被銷毀,只是地址上的值沒了 * 堆內存 * 程序員手動分配 * java:new * c:malloc * 空間不連續(各塊區域由鏈表將它們串聯起來) * 大小取決于系統的虛擬內存 * C:程序員手動回收free * java:自動回收 * 堆上分配的內存稱為動態內存 * 堆的上限是由系統中的有效的虛擬內存來定的,因此獲取的空間較大,且獲得空間的方式也比較靈活 * 堆需由程序員自己申請,申請時指明空間大小,同時堆的內存不連續,易產生碎片,數據執行速度慢 > **棧和堆各有優點,好多時候可以結合使用,比如存儲較大數據時,可以將數據放到堆中,而將指向該數據的指針放到棧中,這樣可以有效地提高程序的執行效率;一般來說,只要不是特大的數據,還是建議使用棧,如函數參數,返回值,局部變量,都存放到棧中,這樣可以大大提高程序的運行速度** **想要數據既不容易被修改,又不會一直占據內存,同時還不局限在某一塊特定區域使用,這時可以使用堆** **堆的使用比較靈活,可隨時申請一個堆也可以釋放掉一個堆,因此堆中的數據不會一直占據著內存,堆既可以在全局申請,也可以在局部申請,因此堆中數據不會只局限在某一塊特定區域,為了保證數據的隱秘性,堆中的每個內存都是匿名的,不用指針,根本無法找到它,因此堆中數據不容易被修改。** **靜態內存分配** ``` #include<stdio.h> #include<stdlib.h> /** 棧內存 系統統一分配統一回收 靜態內存分配 棧內存大小固定的 內存地址是連續的 main()函數和getData()以及getData2()沒有手動地申請內存,那么所占用的都是棧內存, */ int* getData(){ int array[] ={1,2,3,4,5}; printf("getData()中array地址是%#x\n",&array); return &array; } int* getData2(){ int array[] ={5,4,3,2,1}; printf("getData2()中array地址是%#x\n",&array); return &array; } main(){ int* pointer = getData();//getData()函數執行完,內存會被馬上回收,執行getData2()時實際上還是用的getData()的內存 getData2();//通過控制臺輸出結果可知,pointer指的是同一塊內存 printf("%d,%d,%d\n",*(pointer+0),*(pointer+1),*(pointer+2));//棧內存,系統統一分配統一回收,只能用一次, printf("%d,%d,%d\n",*(pointer+0),*(pointer+1),*(pointer+2));//再次打印時,內存被回收或者部分被回收,所以打印出來的值就是隨機的 printf("pointer值為%#x\n",pointer); system("pause"); } ``` 輸出結果 ``` getData()中array地址是0x60febc getData2()中array地址是0x60febc 5,4,3 6,6356652,3 pointer值為0x60febc ``` **動態內存分配** ``` #include<stdio.h> #include<stdlib.h> /** java new對象就會申請一塊堆內存 c malloc memory allocation 內存分配 c的堆內存 程序員手動申請手動釋放 malloc free 申請一塊堆內存 動態內存分配 堆內存 不連續的 堆內存大小不固定 取決機器的狀態 */ main(){ //malloc 接收的參數 申請內存大小 返回一個內存地址值 申請到的也是一塊連續的內存空間 int* pointer = malloc(sizeof(int)*5); *(pointer+0) = 1; *(pointer+1) = 2; *(pointer+2) = 3; *(pointer+3) = 4; *(pointer+4) = 5; //C for 循環 循環的臨時變量i 要先聲明再使用 int i; for(i = 0;i<5;i++){ printf("第%d個元素的值= %d\n",i,*(pointer+i)); } free(pointer); printf("第一個元素的值%d\n",*(pointer+0)); system("pause"); } ``` 輸出結果 ~~~ 第0個元素的值= 1 第1個元素的值= 2 第2個元素的值= 3 第3個元素的值= 4 第4個元素的值= 5 第一個元素的值0 ~~~ > malloc函數在stdlib.h中聲明,該函數的作用是想系統申請指定字節的內存空間,假如給malloc函數傳遞4,則表示申請4個字節的內存空間,之所以用sizeof(int)代替4,是因為int在不同的編譯環境下所占用的字節數是不一樣的,malloc函數的返回值類型是void*,表示未確定類型的指針 **申請內存空間失敗,對malloc函數返回值進行判斷** ``` #include <stdio.h> #include <stdlib.h> //包含malloc函數的聲明 #include <LIMITS.h> int main() { int *p=(int*)malloc(2147483648); if (p==NULL) printf("申請內存空間失敗"); else { *p=4; printf("%d",*p); } return 0; } ``` > **由于計算機內存有限,可能會出現因內存不足而無法滿足malloc函數請求的情況,這種情況下,malloc函數會返回null,該值被賦給指針后,則該指針就是一個空指針,空指針不會指向有效數據,因此在調用malloc函數申請內存空間時,一定要進行返回值的判斷,而且調用malloc函數申請的空間是不連續的,因此可看做是堆** **釋放指針指向的堆空間** ``` #include <stdio.h> #include <stdlib.h> //包含malloc函數和free函數的聲明 int main() { int *p=(int*)malloc(sizeof(int)); *p=400; printf("%d\n",*p); free(p); printf("%d\n",*p); p=0;//當使用free函數釋放p所指向的內存空間后,最好將該指針所保存的內存地址清零,以免重復操作該地址,導致出錯 p=(int*)malloc(sizeof(int)); *p=6; printf("%d\n",*p); free(p);//再次將內存回收 return 0; } ``` 輸出結果 ~~~ 400 0 6 ~~~ > **malloc函數申請的內存空間不會被系統自動釋放,因此假如用戶不去釋放它,則該區域的內存將始終不能為其它數據所使用,為了釋放malloc函數申請的內存空間,必需使用free函數** **使用free函數的注意事項** - free函數釋放的是指針所指向的內存空間,由于不能將同一塊內存連續釋放兩次,因此不能調用兩次free函數來釋放同一塊內存 - free函數只會釋放指針指向的內存空間,并不會釋放指針所占用的內存,因此指針還存在,而且它仍然保持著原來的內存空間地址,如果再次使用該指針,會出現意想不到的情況 **內存泄漏** ``` #include <stdio.h> #include <stdlib.h> //包含malloc函數和free函數的聲明 void create() { int *p=(int*)malloc(sizeof(int));//create函數中申請一塊內存空間,并由p來保存該空間的地址, //指針p是個局部變量,因此當create函數調用完畢,指針p就不存在了,p指向的內存空間這也就再也找不到了, //造成內存丟失,一直到程序結束,p指向的內存空間方才由系統回收。因此假如使用完一塊內存空間,則請立即使用free函數將其釋放 } int main() { create(); return 0; } ``` > **并不是只有指針丟失才會造成內存泄漏,指針保存的地址也會造成內存泄漏;指針變量只能保存一個地址,如對它重新賦值,則表示以前的地址被覆蓋,假如該地址的內存空間沒有被釋放,則將無法再次通過指針來訪問它,因為此時的指針保存的是新的內存空間地址** **迷途指針** ``` #include <stdio.h> #include <stdlib.h> //包含malloc函數和free函數的聲明 int main() { int *p=(int*)malloc(sizeof(int)); long *p1; *p=1; printf("將1賦給p指向的空間后,指針p讀取到的值:\t\t%d\n",*p); free(p);//刪除p指向的空間,這樣p就成了一個迷途指針,因為它指向的空間已經不存在了,但是p仍然保存著原來的內存空間的地址, //這時如果再次嘗試使用該指針,則將會出現意料不到的情況,為了避免出現這種情況,可以在free(p)之后將指針p賦值為0, //盡管說使空指針是非法的,容易使程序崩潰,但是寧愿程序崩潰也不愿調試起來困難 //p=0;//由于空指針指向的通常不是存在的內存空間,因此導致程序運行過后立即崩潰,從而使我們迅速察覺到是指針出了問題 printf("釋放內存后,指針p讀取到的值:\t\t\t%d\n",*p);//再次打印p的值發現成了隨機產生的一個數而不是1 p1=(long*)malloc(sizeof(long)); printf("申請新內存塊后,指針p保存的地址:\t\t%p\n",p); *p1=0; printf("指向新內存塊的指針p1保存的地址:\t\t%p\n",p1); *p=2; printf("將2賦給p指向的空間后,指針p讀取到的值:\t\t%d\n",*p); printf("將2賦給p指向的空間后,指針p1讀取到的值:\t%ld\n",*p1); free(p1); return 0; } ``` #### 指令指針 **指令指針是在寄存器中存放的一種指針,它用來存放下一條待執行指令的地址。每條指令都有一個地址**
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看