數組與指針

數組與指針是內存管理的關鍵,也是C/C++中較難掌握的的地方。現在對其進行一些分析與總結。
 
 一。內存分配方式有四種:

        1.從靜態存儲區域分配。內存在程序編譯的時候就已經分配好,這塊內存在程序的
          整個運行期間都存在。例如全局變量,static 變量,即使是局部static變量(即函數內部定義的static變量)。
          如:
          const char *func()
          {
               static char res[256]={0};
               ...
               return res;  // this is correct.
          }


        2.在棧上創建。在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,函
         數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置於處理器的指令集
         中,效率很高,但是分配的內存容量有限。
          const char *func()
          {
               char res[256]={0};
               ...
               return res;  // this is wrong.
          }
 


       3.從堆上分配,亦稱動態內存分配。程序在運行的時候用malloc 或new 申請任意多
          少的內存,程序員自己負責在何時用free 或delete 釋放內存。動態內存的生存期
          由我們決定,使用非常靈活,但問題也最多。堆內存的釋放必須用free或delete顯式釋放,
         否則要等到程序結束後由操作系統負責收回。
         const char *func()
          {
               char* res=new char[256];
               ...
               return res;  // this is correct.
          }
 
      4.文字常量區。常量就放在這裏,即使是局部定義的常量也放在文字常量區,內容不可以被更改,如常量字符串,一直到程序結束後才由系統釋放。例如:
                const int* func(void)
                {
                    const int x=2;
                    return &x;
               }


              const int *y=func();
              cout<<*y<<endl;// result is 2.
 
 
二。數組與指針的特點分析:


        數組的特點分析:


        1.數組長度必須在編譯時確定;
        2.數組長度不可變;
        3.數組存在於棧中,只在定義它的語句塊內存在;
        4.數組名錶示數組第一個元素的地址(它也是指針,也是迭代器,但只能作爲右值),但是用sizeof操作符計算其大小是該數組所佔的字節數,而不是數組名本身的字節數,唯一的例外是當數組作爲函數的參數傳遞時,數組名自動退化爲同類型的指針。例如:
           int a[10];
           cout<<sizeof(a)<<endl;// result is 40
           void func(int  a[10])
           {
               cout<<sizeof(a)<<endl;//result is 4
           }
           動態分配數組返回的指針的特點分析:


           1.數組長度在編譯時不需要知道;
           2.一旦分配,數組長度不可變;
           3.存在堆中,除非顯示地釋放,它一直存在,即使程序已經結束;
           4.無數組名,只有返回的指針。該指針跟一般指針完全一樣,如用sizeof 操作符計算其大小,得到是該指針所佔內存(32位系統中,指針佔4位),而不是其指向的數組所佔的內存。如:
            int a[10];
            int *p=a;
           cout<<sizeof(p)<<endl;// result is 4
            p=new int[10];
            cout<<sizeof(p)<<endl;// result is 4
 
          一般指針的特點分析:


          C/C++中無法知道指針所指內容的內存容量,而只能知道指針本身所佔的內存。
          sizeof( 指針名)永遠爲4(在32位系統中),而不管指針指向的是不是數組,指向的內存在堆內還是在棧內。
 
三。C-風格字符串:


        1.C風格字符串:
           以空字符null結束的字符數組即爲C風格字符串。
        2.字符串字面值:
            (1)類型:const char*,即不可更改的字符串。
            (2)存儲位置及生命期:存儲在文字常量區,一直到程序的結束。
            (3)與數組關係:可以初始化(const char 或char型)數組,實質就是拷貝初始化,因此初始化後數組與文字常量區中的該字符串字面值無關了。
                      如:char a[]="hello world";
                              a[0]='s';// ok
                      又如:
                      char *GetString(void)
                      {
                          char p[] = "hello world";
                          return p; // 編譯器將提出警告
                      }
                     char *str = NULL;
                      str = GetString(); // str 的內容是垃圾,注意函數返回後,str不爲NULL,但其指向的棧內存已經被釋放了。
                    
 
            (4)與指針關係:可以初始化或賦值給const char* 或char* 類型的指針,此指針指向的是文字常量區中的字面值常量的地址,因此不可以通過該指針修改其內容,
                      而且其內容和地址知道程序結束均不變。
                     如:char *p="hello world";
                              p[0]='s';// error
                    char *GetString(void)
                      {
                          char *p = "hello world";
                          return p;                      
                      }
                     char *str = NULL;
                      str = GetString(); // str 的內容是"hello world", 但注意str指向的是文字常量區裏字面值的指針。
 
        3.C風格字符串的標準庫函數:
            標準庫strting.h裏的以str開頭的函數均是C風格字符串的標準函數。
            這些函數要求C風格字符串:以NULL結尾的字符數組,接受char型數組名或char*型指針。
        4. strlen與sizeof 的區別:
           (1)strlen 只接受char* 型指針或char型數組名,而sizeof 接受任何類型的對象或任何類型名;
           (2)strlen對char* 指針和char型數組名是完全一樣的,而sizeof 對指針和數組名是不一樣的:對指針結果爲4,對數組名結果是該數組所佔的內存空間;
           (3)strlen計算C風格字符串的長度,不包括最後的null字符,而sizeof對char型數組名計算的長度包括最後的Null字符。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章