首先,來看一下下面這段代碼:數組
#include <stdio.h> #include <string.h> int main() { char *str = "media"; char *tmp = "aaa"; printf("str: %s\n",str); strcat(str,tmp); printf("str: %s\n",str); return 0; }
代碼打眼兒一看,功能很明顯:把str指針指向的字符串和tmp指針指向的字符串鏈接起來再賦給str指向的字符串。咱們把這個程序運行一下,以下圖:
報出了段錯誤,使用cgdb調試一下,發現問題是出在strcat函數處:
感受很奇怪,就去查找了strcat函數的一些示例,發現幾乎全部的strcat的示例都是鏈接的兩個數組類型字符串或者一個數組類型一個指針類型(指針類型指向的字符串必定是接在數組字符串以後)。本身手動測試了一下,把*str
改成了str[20]
,發現程序成功運行:
後通過一系列的文檔查閱,得知定義爲指針所指向的字符串是常量字符串,只能讀取不能寫入。運行過程當中,指針變量p所指向的內存是分配在堆中的,且只分配了足夠其指向的內容的內存。將q鏈接到p後,天然p是沒有其餘空間給q了,因此發生了段錯誤。要鏈接這樣的字符串,得另外開闢一個空間存放鏈接起來的字符串。若是非要將兩個變量定義爲指針類型,能夠把程序修改成如下形式:函數
#include <stdio.h> #include <string.h> int main() { char *str = "media"; char *tmp = "aaa"; char *res = (char *)malloc(strlen(str)+strlen(tmp)+1); printf("str: %s\n",str); strcat(strcpy(res,str),tmp); printf("str: %s\n",res); return 0; }
獲得的結果正確:
測試
這學期上了一門課,須要在Linux C中完成一個項目。其中有一個功能模塊是在指定文件夾目錄下遞歸查找當前目錄下的全部文件,並將全部的文件的路徑存入一個數組中。其實遞歸查詢當前文件目錄下的全部文件這個功能並不難,網上也有不少實現方法。我所遇到的問題又出在了數組和指針的問題上(指針涉及的對內存的操做真的是C的最大難點。。),下面是問題具體描述:
我所要實現的功能是,在main的參數中指定了所要掃描的文件夾,在指定文件夾下掃描全部的文件,並把所掃描到的全部文件的路徑存入一個數組中。我使用了dirent.h頭文件中定義的結構體,當d_type == 8是文件,d_type == 4時是文件夾。等於4時便遞歸調用函數實現掃描文件夾下的全部文件,發現一個,printf一個。而後定義了一個全局的char數組指針path來指向所掃描到的文件路徑,在main函數下輸出path來驗證路徑是否正確的存入了數組。主要代碼以下:
而後我所要掃描的文件夾file下有三個txt文件,分別是1.txt、2.txt、3.txt:
在運行程序的時候,出現了問題:在執行readfilelist函數的時候,能夠成功的發現並輸出file文件夾下的三個txt文件,但是path中所存放所找到的文件路徑彷佛並不正確,數組中全部的值都相同,且都是最後一個所找到的文件的路徑,以下圖所示(path array has following data下面輸出的路徑是path數組指針中的數據):
很奇怪,在readfilelist中printf一下每一次循環path中的值試試看吧,發現每一次循環輸出的path中的值是正確的(以下圖#後的輸出結果)????????這就至關於,逐步輸出path中的值是正確的,在main中從新for循環遍歷一下結果就變了,path仍是一個全局變量不存在生存期的問題。並且逐步輸出的時候數組下標count都是及時++的,若是是遞歸返回時的問題,不可能下標已是3了程序還能將數組退到0、一、2位置更改數組中的值吧。這也太奇怪了。。。。
這個結果只能有一種解釋:在逐步將文件路徑存入數組相應的位置時,數組全部的位置的值同時都被改變了。不過我仍是不能理解爲何會發生這樣的問題,立馬打開cgdb。。
display一下path和局部變量ingpath(ingpath是普通字符數組類型,做用是當文件類型是文件時,將文件路徑鏈接完整,再統一賦值給path),看看他倆的值和地址究竟是怎麼變化的。
第一次掃描到3.txt文件,將值存入path中,地址後四位爲d5f0:
繼續執行,又找到了1.txt文件,在操做數組ingpath時出現了問題:尚未執行到給path賦值,只是在對ingpath進行修改操做時,path中的內容也發生了改變:
繼續執行觀察到給path賦值,發現確實和以前的猜測同樣,逐步將文件路徑存入數組相應的位置時,數組全部的位置的值同時都被改變了:
而且,全部通過ingpath所給path賦的值的內存地址都是相同的,都是d5f0。至此,破案了:在將數組指針path的地址指向數組變量ingpath時,path就已經綁定ingpath的地址了(和C++11中的引用&用法有些相似),數組變量的內存地址不會發生改變,並且全部對於ingpath的操做也會相應的對path進行操做。path數組指針的每一位存入數據的內存地址都相同,天然所對應的數據就相同,進而path中全部的值都是相同的。
如何對此進行改進呢。個人想法是:把ingpath的類型也改成指針類型,做爲局部變量,每一次循環開始時都從新爲ingpath指針指向的常量空間從新malloc一下,這樣就保證了ingpath指向的內存地址每一次循環都被從新分配而不會相同,進而「解除」了與path所指向內存地址的綁定。這樣的話,對ingpath指向的地址中的值進行修改就不會影響到path指向的地址中的值,保證了ingpath順利存入path的相應位置。
按照這個思路,對代碼進行了修改:
果不其然,輸出path,正確的輸出了全部文件的路徑:
spa
一個小問題,只須要修改一行代碼就解決了的問題折騰了一天時間(此處,真的想發送一個圍笑^_^)。不過期間沒有白折騰,基本搞清楚了指針和數組相關的問題,收穫良多,仍是很開心的。把這個debug的過程寫出來做爲一個分享。
最後,敲黑板:指針只是一個內存地址的引用,指向內存地址空間。若是在其餘地方更變了這個地址空間裏的數據,指針指向該地址空間中的值也會隨之改變(廢話,不都是一個值麼)。debug