拷贝函数
拷贝函数
该文记录 C/C++
基础拷贝函数使用及区别。
拷贝函数
1 strcpy
1
char *strcpy( char *dest, const char *src );
复制 src
所指向的空终止字节字符串,包含空终止符,到首元素为 dest
所指的字符数组。
2 strncpy
1
2
3
4
5
6
7
8
9
10
char *strncpy( char *dest, const char *src, size_t count )
{
char *start = dest;
while (count && (*dest++ = *src++))
count--;
if (count)
while (--count)
*dest++ = '\0';
return(start);
}
复制 src
所指向的字符数组的至多 count
个字符(包含空终止字符,但不包含后随空字符的任何字符)到 dest
所指向的字符数组。
若在完全复制整个
src
数组前抵达count
,则结果的字符数组不是空终止的。- 若在复制来自
src
的空终止字符后未抵达count
,则写入额外的空字符到dest
,直至写入总共count
个字符。 - 若字符数组重叠,若
dest
或src
不是指向字符数组的指针(包含若dest
或src
为空指针),若dest
所指向的数组大小小于count
,或若src
所指向的数组大小小于count
且它不含空字符,则行为未定义。
3 memcpy
1
2
3
4
5
6
7
8
9
10
void* memcpy( void *dest, const void *src, size_t count )
{
void * ret = dest;
/*
* copy from lower addresses to higher addresses
*/
while (count--)
*dest++ = *src++;
return(ret);
}
从 src
所指向的对象复制 count
个字符到 dest
所指向的对象。两个对象都被转译成 unsigned char 的数组。 若访问发生在 dest 数组结尾后则行为未定义。若对象重叠(这违背 restrict
契约) (C99 起),则行为未定义。若 dest
或 src
为非法或空指针则行为未定义。
4 memmove
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void* memmove( void* dest, const void* src, size_t count )
{
void * ret = dest;
if (dest <= src || dest >= (src + count)) {
/*
* Non-Overlapping Buffers
* copy from lower addresses to higher addresses
*/
while (count--)
*dest++ = *src++;
}
else {
/*
* Overlapping Buffers
* copy from higher addresses to lower addresses
*/
dest += count - 1;
src += count - 1;
while (count--)
*dest-- = *src--;
}
return(ret);
}
从 src
所指向的对象复制 count
个字节到 dest
所指向的对象。两个对象都被转译成 unsigned char
的数组。对象可以重叠:如同复制字符到临时数组,再从该数组到 dest
一般发生复制。若出现 dest
数组末尾后的访问则行为未定义。若 dest
或 src
为非法或空指针则行为未定义。
5 注意
5.1 memcpy与memmove
memcpy
是从前往后复制,memmove
会判断是否地址覆盖然后选择从前往后复制还是从后往前复制。
- 情况一:两个不相邻地址。直接使用
memcpy
。 - 情况二:相邻地址,目标地址在源地址前面或目标地址在源地址后面相距超过复制长度。使用
memcpy
。 - 情况三:相邻地址,目标地址在源地址后面且相距小于复制长度,必须使用
memmove
防止数据覆盖。
参考
本文由作者按照 CC BY 4.0 进行授权