我正在重寫 libc 的一部分,更具體地說是 memmove 作為練習,在我自己無法完成之后,我查找了它的源代碼并發現了這個(以及它的變體):
void *memmove(void *dest, const void *src, size_t n)
{
char *d = dest;
const char *s = src;
if (d < s)
while (n--)
*d = *s ;
else
{
char *lasts = s (n-1);
char *lastd = d (n-1);
while (n--)
*lastd-- = *lasts--;
}
return (dest);
}
我的問題是關于5號線if (d < s)對我來說這只會意義,如果d與s含有兩者的大小dest和src其至于我的理解去是不正確的。那么除了檢查地址的位置之外,這種比較是否還有其他作用,還是我對指標的理解完全有缺陷?
這段代碼有什么目的嗎?如果我完全錯誤,請提前抱歉,指標可能會非常混亂。
uj5u.com熱心網友回復:
函式 memmove 假定源陣列和目標陣列是重疊的。也就是說,它們是指向同一陣列不同部分的指標。所以例如這個 if 陳述句
if (d < s)
檢查陣列中指標 d 所指向的元素是否在指標 s 所指向的元素之前。
考慮一個例子。假設宣告了一個陣列
char s[] = "Hello World!";
即包含字串的陣列"Hello World!"。并且您想要更改陣列,使其包含字串“World!”。您需要的是移動包含子字串“World!”的源字串部分。到陣列的開頭。
如果你會寫
strcpy( s, s 6 );
那么這樣的呼叫會呼叫未定義的行為,因為函式 strcpy 不允許使用重疊的子陣列。
使用 memmo 你可以寫
memmove( s, s 6, 7 );
在這種情況下,相對于您提供的函式定義,指標 d 具有原始陣列 s 的值,指標 s 具有等于運算式 s 6 的值。
由于 d 的值小于指標 s 的值,因此這部分函式獲得控制權
if (d < s)
while (n--)
*d = *s ;
注意根據C標準(6.5.8關系運算子)
5 比較兩個指標時,結果取決于所指向物件在地址空間中的相對位置。如果指向物件型別的兩個指標都指向同一個物件,或者都指向同一個陣列物件的最后一個元素之后的一個,則它們比較相等。如果指向的物件是同一個聚合物件的成員,則指向后面宣告的結構成員的指標比較大于指向結構中前面宣告的成員的指標,指向具有較大下標值的陣列元素的指標比較大于指向同一陣列元素的指標具有較低的下標值。指向同一聯合物件成員的所有指標比較相等。如果運算式 P 指向陣列物件的一個??元素,而運算式 Q 指向同一陣列物件的最后一個元素,則指標運算式 Q 1 比較大于 P。在所有其他情況下,行為未定義。
那是從引文中得出的結論是,傳遞給函式 memmove 的兩個指標應指向同一陣列的元素,以保證此 if 陳述句中指標比較的定義行為
if (d < s)
否則行為是未定義的。
uj5u.com熱心網友回復:
除了檢查地址的位置之外,這個比較還有什么作用嗎?
不。它檢查d地址是否低于s。如果是,則選擇第一個策略,從記憶體區域的開頭向前復制 - 否則從記憶體區域的結尾向后復制
這是為了不弄亂結果以防萬一[d,d n)并且[s,s n)重疊。
例子:
--- --- ---
src | x | y | z |
--- --- --- ---
dest | | | |
--- --- ---
^ ^
| |
low mem addr high mem addr
這里必須選擇第二種策略。考慮如果選擇第一個策略會發生什么:
dest[0] = src[0]; // which is x
dest[1] = src[1]; // which is ... x, because the above op overwrote the y
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/336490.html
下一篇:檢測輸入是字符還是數字
