Re: [問題] 用memcpy 會有殘餘值怎麼辦?

看板C_and_CPP作者 (overhead)時間9年前發表 (2016/02/03 16:21), 9年前編輯推噓13(13018)
留言31則, 7人參與, 最新討論串2/3 (看更多)
我沒有仔細看你的本文,不過針對你補充的部分: Ptr->ListString = (char *)malloc ((Length + 1) * sizeof(char)); memset (Ptr->ListString, '\0', Length + 1); memcpy (Ptr->ListString, CharPtr, Length); strcat (Ptr->ListString , "\0"); printf ("%s", Ptr->ListString); printf (" %d\n",Length); 有些建議 1. strxxx系列function以及%s顧名思義都是在處理string string的定義就是結尾為0(='\0')的char array 因此你沒有放'\0'在結尾之前,都別用這些functions,會壞掉 (這也是為啥有strxxx_s系列的理由) 2. memxxx系列的效率比strxxx系列高很多 因為後者除了要處理array以外,還要隨時注意'\0'到了沒 3. 雖然memxxx比較快,但copy本質上就是比用指標重複利用一塊data來得慢 所以盡量用指標處理資料傳遞,當然用指標比較難而且比較多限制就是 4. 如果你打定主意這個array都要用string形式處理,那memset就不用做了 浪費成本 舉個例子: a[0]='A', a[1]='B', a[2]='\0', a[3]='C' b[0]='A', b[1]='B', b[2]='\0', b[3]='\0' 用printf("%s %s", a, b)印出來的a,b字串是一模一樣的,都是AB 不管a[3]是多少,從s[0]開始掃到a[2]發現有'\0'時,電腦就會結束掃下去了 5. 承第一點,strcat的意思是"在str開始第一個出現'\0'的位置後面接上指定字串" 言下之意是,如果你能接上指定字串"\0",代表它前面有個'\0' 另外"\0"是個字串,裡面有\跟0,用單引號包起來的'\0'才是0的意思 你strcat (Ptr->ListString , "\0");這一行是一點意義也沒有的 真正幫你補0的是你一開始的memset (Ptr->ListString, '\0', Length + 1); 可如同我第四點所說的,你這樣做是有點浪費成本的 因為[0]~[Length]才改完的值隨即會被memcpy蓋過,很心酸~ (也是可以寫啦,看風格,有人覺得浪費點成本但是初始時寫memset比較整齊) 建議如下: Ptr->ListString = (char *)malloc ((Length + 1) * sizeof(char)); memcpy (Ptr->ListString, CharPtr, Length); //等同[0]~[Length-1]裡放滿值 *(Ptr->ListString + Length) = '\0'; //[Length]放'\0',等同補成完整string printf ("%s", Ptr->ListString); //因為[Length]放'\0',所以可以正常顯示 printf (" %d\n",Length); -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 118.166.43.139 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1454516460.A.04E.html ※ 編輯: overhead (118.166.43.139), 02/04/2016 00:21:58 ※ 編輯: overhead (118.166.43.139), 02/04/2016 00:26:17

02/04 00:42, , 1F
"\0" 是 char 陣列 {(char)0, (char)0} 喔
02/04 00:42, 1F

02/04 00:42, , 2F
"\\0" 才是 {'\\', '0' ,'\0'}
02/04 00:42, 2F

02/04 00:52, , 3F
嗚喔!原來如此
02/04 00:52, 3F

02/04 09:20, , 4F
受教了
02/04 09:20, 4F


02/04 11:18, , 6F
我看這個字串表示 \0 也是代表空字元阿
02/04 11:18, 6F

02/04 11:19, , 7F
\"表示忽略(Escape)字元
02/04 11:19, 7F

02/04 13:07, , 8F
很用心耶。不過第二點我覺得有點要修正,就Big O來看兩者
02/04 13:07, 8F

02/04 13:07, , 9F
相對應的memxxx和strxxx當n相同,常數忽略,二者的Big O
02/04 13:07, 9F

02/04 13:07, , 10F
相同。如果要細究到常數,跟平台會有關,簡單說你要計算CP
02/04 13:07, 10F

02/04 13:07, , 11F
U二者程式全部指令集所耗T數,因CPU可能會強化一些行為,
02/04 13:07, 11F

02/04 13:07, , 12F
就不能看code去分析了。說錯的地方在討論吧。
02/04 13:07, 12F

02/04 18:25, , 13F
請愛用strn系列
02/04 18:25, 13F

02/05 00:23, , 14F
不要隨便推廣 strn 系列...它反而是最需要小心使用的函式
02/05 00:23, 14F

02/05 10:27, , 15F
來用snprintf()嘛~好用耶,不試看看嗎?
02/05 10:27, 15F

02/05 22:05, , 16F
不過string有分zero-terminated跟沒有的吧?
02/05 22:05, 16F

02/05 22:07, , 17F
*null
02/05 22:07, 17F

02/07 01:00, , 18F
"最需要"小心使用是從何而來?我以為strn是應str的問題
02/07 01:00, 18F

02/07 01:00, , 19F
生出來的不是嗎?
02/07 01:00, 19F

02/07 01:05, , 20F
對我來說看到n就知道我要注意了,光這點就完勝str系列
02/07 01:05, 20F

02/07 01:14, , 21F
問題不在 n 而在他屬於 str 系列函式
02/07 01:14, 21F

02/07 01:14, , 22F
所有 str 系列只有 strn 不加尾巴的 '\0'
02/07 01:14, 22F

02/07 01:14, , 23F
memcpy/memmove 不是 str 系列會特別注意使用狀況
02/07 01:14, 23F

02/07 01:15, , 24F
但 str 系列因為其他都會加 '\0' 就這個不會
02/07 01:15, 24F

02/07 01:16, , 25F
才會說要特別注意使用
02/07 01:16, 25F

02/08 00:36, , 26F
都有個N了,還幫你加一個字元不是很奇怪?
02/08 00:36, 26F

02/08 00:42, , 27F
我知道了,這是思考邏輯的不同。你是從str系列來思考,
02/08 00:42, 27F

02/08 00:43, , 28F
我是從有個n來思考
02/08 00:43, 28F

02/08 01:11, , 29F
有 n 也不一定不加喔, snprintf 就會加 '\0'
02/08 01:11, 29F

02/09 23:59, , 30F
臉丟大了(掩面),我的確不知道snprintf會加null囧,目前
02/09 23:59, 30F

02/09 23:59, , 31F
沒出過問題應該是我習慣把buffer會多加一點…感謝指正
02/09 23:59, 31F
文章代碼(AID): #1MiYZi1E (C_and_CPP)
文章代碼(AID): #1MiYZi1E (C_and_CPP)