看板 C_and_CPP 關於我們 聯絡資訊
開發平台(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
loveme00835: 你知道 char *a = "abcd"; 和 char a[] = "abcd"; 之07/24 01:13
loveme00835: 間的差別嗎?07/24 01:13
一個是pointer, 一個是array? (好像廢話)
galic: 這個真的神 誤打誤撞 他的strcopy結果等同a = b;07/24 01:15
galic: 等於是把a指標改指向跟b指標指向的位址相同...07/24 01:15
galic: 老闆應該幫你加薪 不但完成了需求 而且效能更佳07/24 01:16
瘋了...違背我的本意 我剛剛執行完,確實兩者的位址相同了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
loveme00835: 那你知道兩者指向的空間有什麼差異嗎?07/24 01:25
前者為一個pointer,指向一個string, 後者為一個array,所有array的操作都可以做 所以是不是pointer所指的string是read-only的? ※ 編輯: ericerix (118.160.241.74 臺灣), 07/24/2021 01:33:08 我把*a改成a[]的形式就可以用b做了
loveme00835: 那個叫做 string literal 不是 string, 當編譯器看到 07/24 01:35
※ 編輯: ericerix (118.160.241.74 臺灣), 07/24/2021 01:35:51
loveme00835: string literal 時會偷偷建立陣列來儲存對應的字元,07/24 01:36
loveme00835: 這個陣列的生命週期很長, 而且你不能改變它的內容,07/24 01:37
我查到pointer是存在stack區,而他所指的連續位址是存在static那裡(.data)
loveme00835: 所以雖然可以用 char* 指向這個陣列去讀取內容, 不用07/24 01:38
loveme00835: 強制加 const 是因為從 ANSI C 開始就很多這種程式碼07/24 01:39
loveme00835: , 所以一直沿用至今. 如果只是單純參考 string liter07/24 01:41
loveme00835: al 的記憶體, 最好加上 const; 如果你是要儲存字串處07/24 01:41
loveme00835: 裡的結果, 就得另外定義陣列. char a[] = "abcd"; 這07/24 01:43
loveme00835: 種定義方式就是另外創一個陣列, 然後它會有和 string07/24 01:44
loveme00835: literal "abcd" 相同的內容. 所謂的字串是指以 '\0'07/24 01:44
loveme00835: 結尾的資料流, 而必須有連續的記憶體區塊才能裝這個07/24 01:45
char *d = "1234"; d = "3456"; printf("%s\n", d); 輸出為3456 那為什麼這樣可以修改值呢? ※ 編輯: ericerix (118.160.241.74 臺灣), 07/24/2021 01:47:45
loveme00835: 資料流, 那最常見的就是用陣列或是動態記憶體配置,07/24 01:46
loveme00835: 利用 string literal 建立的陣列因為唯讀的特性, 通07/24 01:49
loveme00835: 常只會用在如 printf() 的格式字串上 07/24 01:50
loveme00835: 因為有兩個 string literal "1234" 還有 "3456", 你07/24 01:51
loveme00835: 沒有改變陣列的內容, 你只是將原本指向 "1234" 陣列07/24 01:52
loveme00835: 的 d 改指向 "3456" 而已, 不信的話你用 %p 印出 d07/24 01:52
loveme00835: 的值就知道, 所謂的"修改字串值"意思是在同一塊記憶 07/24 01:53
loveme00835: 體上面修改字元內容.07/24 01:54
loveme00835: C 語言字串不是變數, 字串是資料流07/24 01:55
loveme00835: 用 char* 定義的變數不是字串, 只是指向資料流的指標07/24 01:58
我的天,謝謝你的詳細講解 完全懂了!好感人 ※ 編輯: ericerix (118.160.241.74 臺灣), 07/24/2021 01:59:38
loveme00835: 簡單來說就是陣列複製而已, 只是陣列的元素從 int 換 07/24 02:00
loveme00835: 成 char, 沒什麼特別的 07/24 02:00