問題的來源是自己寫的一個測試代碼:
#include <iostream> using namespace std; int main() { char a[1]; a[0] = 'a'; a[1] = 'b'; char b[1]; b[0] = 'c'; b[1] = 'd'; strcpy(a, b); cout<<"拷貝之后:a[0] = "<<a[0]<<" a[1] = "<<a[1]<<endl; cout<<"拷貝之后:b[0] = "<<b[0]<<" b[1] = "<<b[1]<<endl; return 0; }
在這之后輸出的兩個字符串的值並不是想象中的:
“拷貝之后:a[0] = c a[1] = d
拷貝之后:b[0] = c b[1] = d”
而是:
一開始看到之后一臉懵逼,為啥我用strcpy()拷貝完之后,源字符數組的值反而不對了呢?
於是我多寫了一些測試用的輸出代碼,和顯示兩個字符數組頭在內存中位置的輸出代碼來找出問題所在:
#include <iostream> using namespace std; int main() { char a[1]; a[0] = 'a'; a[1] = 'b'; cout<<"a[0] = "<<a[0]<<" a[1] = "<<a[1]<<endl; char b[1]; b[0] = 'c'; b[1] = 'd'; cout<<"聲明char b[1]后:a[0] = "<<a[0]<<" a[1] = "<<a[1]<<endl; cout<<"b[0] = "<<b[0]<<" b[1] = "<<b[1]<<endl; strcpy(a, b); printf("%x\n",a); printf("%x\n",b); cout<<"拷貝之后:a[0] = "<<a[0]<<" a[1] = "<<a[1]<<endl; cout<<"拷貝之后:b[0] = "<<b[0]<<" b[1] = "<<b[1]<<endl; return 0; }
隨后得到了輸出如下:
可見,在聲明完char b[1]這個小婊砸后,字符數組a中的值就已經被改變了!
這是為什么呢?
可以看到,a和b這兩個字符數組的地址相差只有1,這也就是問題的所在了!
在剛聲明完char a[1]時,內存中是這樣的:
53151adb 'a' // 這里是字符數組a的開始地址
53151adc 'b'
53151add '\0'
而等到char b[1]聲明完后,內存中變成了這樣:
53151ada 'c' // 這里是字符數組b的開始地址
53151adb 'd' // 這里是字符數組a的開始地址,原來的 'a' 被字符數組b中的 'd' 覆蓋了!
53151adc '\0' // 原來的'b'被字符數組b中的結尾符'\0'覆蓋了!
53151add '\0'
這就解釋了為什么char b[1]聲明完后,a[1]變成了'd'的問題。
那么當我們使用了strcpy(a, b)會怎么樣呢?
這個函數會把b中的值一個個復制到a中去,因此復制完之后內存地址長這樣:
53151ada 'c' // 這里是字符數組b的開始地址
53151adb 'c' // 這里是字符數組a的開始地址,剛剛的 'd' 被字符數組b中的 'c' 覆蓋了!
53151adc 'd' // 剛剛的'\0'被字符數組b中的'd'覆蓋了!
53151add '\0'
這時候,再輸出字符數組a和b的時候,就呈現了一開始我們看到的一坨&%&%¥%@……嗯。
歡迎大家在評論區留言交流~