程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C/C++要點全掌握(二)

C/C++要點全掌握(二)

編輯:C++入門知識

 

上接C/C++要點全掌握(一)

 

9、堆棧

       棧(stack):為程序保存的一塊內存區域,用來保存狀態數據,其訪問順序是後進先出(LIFO)。例如:過程或函數的地址,參數,有時候還包括局部變量。

 

       堆(heap):為程序保存的一塊內存區域,用來保存那些在運行時才知道其存在與大小的數據;程序能夠從堆中分配內存給這些元素;在用完之後,應該釋放掉這些內存。堆中所有的的東西都是匿名的,不能按名字直接訪問只能通過指針間接的訪問。

 

       所以,堆和棧的區別:一個是動態,一個是靜態; 堆是在程序運行時動態分配的,而棧的分配是編譯完後,就確定了;棧內存的回收,系統自動進行了,而堆上分配的內存,需要手工顯式回收。 

 

       malloc , new分配的內存就是在堆上的,如果不用free, delete回收,就會造成內存洩漏(垃圾),不過,一般操作系統會在整個程序(進程)退出時,回收分配給這個進程的內存等資源。

 

(以下內容摘自百度百科堆棧)

       一個由C/C++編譯的程序占用的內存分為以下幾個部分。

  (1)棧區(stack):由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似於數據結構中的棧。

  (2)堆區(heap):由程序員分配釋放, 若程序員不釋放,程序結束時可能由操作系統回收 。注意它與數據結構中的堆是兩回事,分配方式倒是類似於鏈表。

  (3)全局/靜態區(static): 全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域,未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域。程序結束後由系統釋放。

  (4)文字常量區:常量字符串就是放在這裡的,程序結束後由系統釋放。

       (5)程序代碼區:存放函數體的二進制代碼。

 

這是一個前輩高人寫的,非常詳細。

 

    

    int a = 0;// 全局初始化區  

 

  char *p1;//全局未初始化區  

 

  void main()  

 

  {  

 

    int b; //棧  

 

    char s[] = "abc"; //棧,運行時賦值 

 

    char *p2;// 棧  

 

    char *p3 = "123456";// 123456\0在常量區,p3在棧上。編譯時確定。  

 

    static int c =0;// 全局(靜態)初始化區  

 

    p1 = (char *)malloc(10); //p1指向堆區,p1在棧上 

 

}  

   

關於堆棧的其他信息參見百度百科有關堆棧的介紹。

10、指針辨析

 

int  * p;//指向int型的指針 

 

void  * p;//空類型指針 

 

int *  arr[10];//指針數組x存放10個指向int型的指針 

 

int**  pp;//指針的指針(指向int型的指針的指針) 

 

int  (*func_p)(int,int);//函數指針 

 

注:在C中可以直接將void*指針賦值給其他任意類型指針,而在C++中需使用強制類型轉換。

 

指針使用的典型錯誤

 

//函數功能:對指定的字符指針分配內存。 

 

void func(char* p) 

 

  p=malloc(100); 

 

void main() 

 

 

   char* str=NULL; 

 

   func(str);//給str分配內存 

 

    ... 

   free(str);//用完釋放內存 

       調用函數func(str)貌似給str分配了內存,其實不然。在此形式參數p是一個局部指針變量,調用語句首先用str(在此即NULL,也可以是一個char型數據的內存地址)初始化p,使p和str指向同一位置,之後申請內存空間並將首地址賦給p,此時p與str指向已不同,之後局部變量p被銷毀。整個過程根本就沒有修改str的指向位置,更談不上為str分配內存了。

       通過此例可知並不是形參為指針類型就可以改變實參的值。要達到“引用傳參”的效果必須在函數內給*p賦值。結合上例修改後代碼如下:

 

//使用指針的指針傳參 

 

void func(char** p) 

 

 

   *p=malloc(100); 

 

 

  

 

void main() 

 

 

   char* str=NULL; 

 

   func(&str);// 給str分配內存 

 

   ... 

 

   free(str);//用完釋放內存 

 

 

針對上例,我們還可以通過函數返回值來來傳遞動態內存,代碼如下:

 

char* func() 

 

 

   char *p=malloc(100); 

 

   return p; 

 

 

  

 

void main() 

 

 

   char* str=NULL; 

 

   str=func();// 給str分配內存 

 

   ... 

 

   free(str);//用完釋放內存 

 

 

        malloc函數返回的指針指向“堆區”,但不能通過函數返回值方式返回指向“棧內存”的指針,編譯器將給出“返回局部變量或臨時變量的地址”的警告提示。

 

char* func(int loginNo) 

 

 

   char str1[]="hello tht1";//棧 

 

   char str2[]="hello tht2";//棧 

 

   if(1==loginNo) 

 

      return str1;//警告:返回局部變量或臨時變量的地址 

 

   else return str2;//警告:返回局部變量或臨時變量的地址 

 

 

  

 

void main() 

 

 

   char* str=NULL; 

 

   str=func(1); 

 

   ... 

 


摘自 tht的專欄

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved