【轉】char *str 和 char str[]的區別


轉自】http://blog.csdn.net/hackbuteer1/article/details/6706562    在原文的基礎上稍作修改 
1  char* get_str(void)  
2  {  
3      char str[] = "abcd";  
4      return str;  
5  } 

            char str[] = "abcd";定義了一個局部字符數組,返回它的地址肯定是一個已經釋放了的空間的地址。 此函數返回的是內部一個局部字符數組str的地址,且函數調用完畢后 此數組被銷毀,所以返回的指針也就指向一塊被銷毀的內存,這種寫法得不到想要的結果,是錯誤的。

    

1  char* get_str(void)  
2  {  
3      char *str = "abcd";  
4      return str;  
5  }  

      char* str = "abcd";表示先定義個字符串常量,存儲在文字常量區,然后將其地址賦給str,即str指向字符串“abcd”。 此函數返回的是字符串常量的地址,而像這種字符串都是屬於全局的,在編譯的時候就已經分配了內存了,只有程序退出的時候才會被銷毀,所以返回它的地址是沒有問題的,但是值得注意的是,我們不能去改變字符串的值,因為存儲在文字常量區的字符串只能讀不能寫。另外值得注意的是:這個char型的str指針屬於局部變量,存儲在棧里面,只是字符串在文字常量區,所以函數返回的時候,先將字符串在文字常量區的地址返回,然后作用域結束后釋放str在棧里面的空間。

 
1 const char str[] = "abcd";        //abc存儲在堆棧中  
2 const char *str = "abcd";         //abc存儲在靜態存儲區  

        准確的說,上面兩個“abcd"都是存儲在靜態數據區,即文字常量區。文字常量區是可讀不可寫的。所以任何試圖對常量區進行寫的操作都是非法的,當然了,這也不是一定不可寫的,你可以采取某種渠道改變文字常量區的內存屬性,比如改變pe相關節的屬性就可以對常量區進行讀寫,當然了,這個目前可以忽略。。。
       那么為什么str[] = "abcd";      可以寫呢?   答案就在str[] = "abcd";會有一個額外的拷貝過程,即把文字常量區的 "abcd"拷貝到棧內存去,存入到str數組中,所以就可以寫了。

      總結:
所有以" "或' '包含的字符、字符串都是常量,應該是存儲在堆上。

1 char *str = "xxxxx"//str指向文字常量區中該字符串的地址,“xxxxx”是全局的,但str仍然是局部變量。
2 char str[] = "xxxxx"//str在棧上申請空間,將文字常量區的字符串內容復制進來,所以"xxxxx"變成局部變量。

首先,數組和指針是不同的數據類型,有本質的區別:

1 char str[] = "abcd";         //sizeof(str) == 5 * sizeof(char)
2 char * str = "abcd";        //sizeof(str) == 4(x86) or 8(x64),是個指針,無論什么類型的指針在32位機器上的大小均為4bytes

再然后,"abcd"叫做“字符串常量”,任何類型的常量都是右值(沒有名字的臨時變量),必須讓"abcd"成為左值(有名字的變量),才能夠修改"abcd"這個字符串。

1 char str[] = "abcd";              //等號兩端是相同的數據類型,右值成為左值
2 char * str = "abcd";             //等號兩端是不同的數據類型,右端自動轉型成char*,該str得到了“abcd”的地址,而"abcd"這個char數組仍然沒有名字。

最后 char a[]="Hello";與char aa[8];aa="Hello" 的不同之處在哪為什么第一個對,第二個錯?

1     char a[8];
2     a="Hello"; //error C2440: '=' : cannot convert from 'const char [6]' to 'char [8]'
3     char aa[8]="hello";  //it's ok
4     char *aaa="hello";  //it's ok
為什么必須在定義的時候初始化呢?

    char a[8];這樣定義了一個數組后,數組名a就是個地址常量,也就是指針常量,只能指向該數組在內存地址空間中的首地址。不可以再指向別的地址。所以如果a = "hello";就是把文字常量區的字符數組"hello"的首地址賦給地址常量a,這是不允許的。
     如果寫成char aa[8] = "hello";這就是在定義數組a的時候就對其初始化,把"hello"串的每個字符賦值給數組a的元素,在這里存在一個拷貝的過程。這是合理的。

     char *aaa="Hello";也定義了一個指針,而該指針可以指向文字常量區的字符數組"Hello"的首地址,也可以指向文字常量區的字符數組"world"的首地址。

 

下面通過一個程序具體看一下。【轉自】http://blog.csdn.net/sdlyjzh/article/details/17342541

該程序是為了實現講字符串中的單詞逆序,例如,如果輸入“I am a boy",希望輸出"boy a am I"。

 1 #include <stdio.h>  
 2   
 3 int main(void)  
 4 {  
 5     char *str="I am a boy!";  
 6     void reverse(char *start, char *end);  
 7     void reverseString(char *str);  
 8     reverseString(str);  
 9     puts(str);  
10   
11   
12 }  
13   
14   
15 void reverse(char *start, char *end)  
16 {  
17     char temp;  
18     if(start==NULL||end==NULL)  
19         return;  
20     while(start<end)  
21     {  
22         temp=*start;  
23         *start = *end;  
24         *end=temp;  
25         start++;  
26         end--;  
27     }  
28 }  
29   
30   
31 void reverseString(char *str)  
32 {  
33     if(str==NULL)  
34         return;  
35     char *start,*end;  
36     start=end=str;  
37     while(*end!='\0')  
38     {  
39         end++;  
40     }  
41     end--;  
42   
43     reverse(start,end);  
44   
45     start=end=str;  
46     while(*start!='\0')  
47     {  
48         if(*start==' ')  
49             start=++end;  
50         else  
51         if (*end==' '||*end=='\0')  
52         {  
53             reverse(start,--end);  
54             start=++end;  
55         }  
56         else  
57         {  
58             end++;            
59         }  
60     }  
61   
62 }

程序編譯沒有問題,運行報錯,提示寫入內存0x........時失敗。

根據報錯的地址,發現是

 1 void reverse(char *start, char *end)  
 2 {  
 3     char temp;  
 4     if(start==NULL||end==NULL)  
 5         return;  
 6     while(start<end)  
 7     {  
 8         temp=*start;  
 9         *start = *end;   //出錯  
10         *end=temp;  
11         start++;  
12         end--;  
13     }  
14 }  

也就是給*start寫入數據出錯,原因就是由於主函數中用char *str 創建的字符串是一個常量。只要把他改為char str[]即可。

 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM