[問題]實作strcpy產生bus error的問題

看板C_and_CPP (C/C++)作者 (我的帥,在於臉)時間4年前 (2021/07/24 01:05), 4年前編輯推噓0(0029)
留言29則, 2人參與, 4年前最新討論串1/1
開發平台(Platform): (Ex: Win10, Linux, ...) macOS 編譯器(Ex: GCC, clang, VC++...)+目標環境(跟開發平台不同的話需列出) gcc 額外使用到的函數庫(Library Used): (Ex: OpenGL, ...) 問題(Question): bus error 餵入的資料(Input):預期的正確結果(Expected Output): 正確strcpy 錯誤結果(Wrong Output): bus error 程式碼(Code):(請善用置底文網頁, 記得排版,禁止使用圖檔) 可正確完成: 程式碼a. https://pastebin.com/dic0xAgn 我想問的錯誤程式碼: 程式碼b. https://pastebin.com/6S1VE5nF 另外一種程式碼: 程式碼c. https://pastebin.com/w8J8cxBv 補充說明(Supplement): 不知道是不是我觀念問題錯很大,連續兩篇有關string的位址問題XD 先說,這三個程式碼只差在第13行 a.是我後來突發奇想這樣改,結果對了: strcopy((char *)&a, (char *)&b); b.我一開始是這樣寫的: strcopy(a,b); c.是我用線上編譯器做的,b餵進去會錯,才這樣在線上編譯器改: strcopy(&a,&b); 我一開始在本機的compiler是寫b的程式碼, 一直出現bus error,真的是搞不懂, 因為我有實作另一個strlen,就是用b的方法傳進去, 然後內部s++;count++;這樣 但在copy會錯, 後來在線上編譯器實作b的方法,也會錯, 改成c後,就可以了 但很不合理啊,c這樣傳入的應該是char **,居然會對? 後來在本機的compiler寫a的做法, 我自己覺得很奇怪,為什麼這樣可以,但b不行? 求大大們開示 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 118.160.241.74 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1627059923.A.29A.html

07/24 01:13, 4年前 , 1F
你知道 char *a = "abcd"; 和 char a[] = "abcd"; 之
07/24 01:13, 1F

07/24 01:13, 4年前 , 2F
間的差別嗎?
07/24 01:13, 2F
一個是pointer, 一個是array? (好像廢話)

07/24 01:15, 4年前 , 3F
這個真的神 誤打誤撞 他的strcopy結果等同a = b;
07/24 01:15, 3F

07/24 01:15, 4年前 , 4F
等於是把a指標改指向跟b指標指向的位址相同...
07/24 01:15, 4F

07/24 01:16, 4年前 , 5F
老闆應該幫你加薪 不但完成了需求 而且效能更佳
07/24 01:16, 5F
瘋了...違背我的本意 我剛剛執行完,確實兩者的位址相同了OTZ...... 所以我才想說,b應該會是最適合的? 但卻出現bus error. ※ 編輯: ericerix (118.160.241.74 臺灣), 07/24/2021 01:22:40 ※ 編輯: ericerix (118.160.241.74 臺灣), 07/24/2021 01:24:00

07/24 01:25, 4年前 , 6F
那你知道兩者指向的空間有什麼差異嗎?
07/24 01:25, 6F
前者為一個pointer,指向一個string, 後者為一個array,所有array的操作都可以做 所以是不是pointer所指的string是read-only的? ※ 編輯: ericerix (118.160.241.74 臺灣), 07/24/2021 01:33:08 我把*a改成a[]的形式就可以用b做了

07/24 01:35, 4年前 , 7F
那個叫做 string literal 不是 string, 當編譯器看到
07/24 01:35, 7F
※ 編輯: ericerix (118.160.241.74 臺灣), 07/24/2021 01:35:51

07/24 01:36, 4年前 , 8F
string literal 時會偷偷建立陣列來儲存對應的字元,
07/24 01:36, 8F

07/24 01:37, 4年前 , 9F
這個陣列的生命週期很長, 而且你不能改變它的內容,
07/24 01:37, 9F
我查到pointer是存在stack區,而他所指的連續位址是存在static那裡(.data)

07/24 01:38, 4年前 , 10F
所以雖然可以用 char* 指向這個陣列去讀取內容, 不用
07/24 01:38, 10F

07/24 01:39, 4年前 , 11F
強制加 const 是因為從 ANSI C 開始就很多這種程式碼
07/24 01:39, 11F

07/24 01:41, 4年前 , 12F
, 所以一直沿用至今. 如果只是單純參考 string liter
07/24 01:41, 12F

07/24 01:41, 4年前 , 13F
al 的記憶體, 最好加上 const; 如果你是要儲存字串處
07/24 01:41, 13F

07/24 01:43, 4年前 , 14F
裡的結果, 就得另外定義陣列. char a[] = "abcd"; 這
07/24 01:43, 14F

07/24 01:44, 4年前 , 15F
種定義方式就是另外創一個陣列, 然後它會有和 string
07/24 01:44, 15F

07/24 01:44, 4年前 , 16F
literal "abcd" 相同的內容. 所謂的字串是指以 '\0'
07/24 01:44, 16F

07/24 01:45, 4年前 , 17F
結尾的資料流, 而必須有連續的記憶體區塊才能裝這個
07/24 01:45, 17F
char *d = "1234"; d = "3456"; printf("%s\n", d); 輸出為3456 那為什麼這樣可以修改值呢? ※ 編輯: ericerix (118.160.241.74 臺灣), 07/24/2021 01:47:45

07/24 01:46, 4年前 , 18F
資料流, 那最常見的就是用陣列或是動態記憶體配置,
07/24 01:46, 18F

07/24 01:49, 4年前 , 19F
利用 string literal 建立的陣列因為唯讀的特性, 通
07/24 01:49, 19F

07/24 01:50, 4年前 , 20F
常只會用在如 printf() 的格式字串上
07/24 01:50, 20F

07/24 01:51, 4年前 , 21F
因為有兩個 string literal "1234" 還有 "3456", 你
07/24 01:51, 21F

07/24 01:52, 4年前 , 22F
沒有改變陣列的內容, 你只是將原本指向 "1234" 陣列
07/24 01:52, 22F

07/24 01:52, 4年前 , 23F
的 d 改指向 "3456" 而已, 不信的話你用 %p 印出 d
07/24 01:52, 23F

07/24 01:53, 4年前 , 24F
的值就知道, 所謂的"修改字串值"意思是在同一塊記憶
07/24 01:53, 24F

07/24 01:54, 4年前 , 25F
體上面修改字元內容.
07/24 01:54, 25F

07/24 01:55, 4年前 , 26F
C 語言字串不是變數, 字串是資料流
07/24 01:55, 26F

07/24 01:58, 4年前 , 27F
用 char* 定義的變數不是字串, 只是指向資料流的指標
07/24 01:58, 27F
我的天,謝謝你的詳細講解 完全懂了!好感人 ※ 編輯: ericerix (118.160.241.74 臺灣), 07/24/2021 01:59:38

07/24 02:00, 4年前 , 28F
簡單來說就是陣列複製而已, 只是陣列的元素從 int 換
07/24 02:00, 28F

07/24 02:00, 4年前 , 29F
成 char, 沒什麼特別的
07/24 02:00, 29F
文章代碼(AID): #1W-lRJAQ (C_and_CPP)
文章代碼(AID): #1W-lRJAQ (C_and_CPP)