/*********************************************
* @brief 复制字符串
* @param dest 目标地址
* @param src 源字符串
* @param count 最多复制的字节数
* @return 目标地址
********************************************/
char* strncpy(char* restrict dest, const char* restrict src, size_t count);
!subtitle:说明
将 src 指向的字符串复制到 dest 指向的内存,最多复制 count 字节。
如果 src 指向的字符串长度大于等于 count 字节,复制到 dest 时将缺少结尾的 0。
注意:
dest 必须有足够的空间
dest 和 src 指向的字符串不可以存在重叠
!subtitle:参数
dest - 指向要复制到的内存地址
src - 指向要被复制的字符串
count - 最多复制的字节数,包括结尾的 0
!subtitle:返回值
返回目标地址 dest 本身
#include <stdio.h>
#include <string.h>
int main(void)
{
char dest [10];
strncpy(dest, "hello", 10); // count 为 10 确保 dest 不会越界
dest[9] = 0; // 确保以 0 结尾
printf("%s\n", dest);
strncpy(dest, "Never gonna give you up.", 10); // count 为 10 确保 dest 不会越界
dest[9] = 0; // 确保以 0 结尾
printf("%s\n", dest);
return 0;
}
说明:
复制时指定最大长度为 dest 数组的长度 10,避免越界
复制后将 dest 的最后一个元素设为 0,确保字符串以 0 结尾
复制 "hello" 时,复制了结尾的 0;dest[9] = 0 不是必要的,但也不会产生错误
复制 ""Never gonna give you up." 时,超出长度 10,中间截断,没有复制结尾的 0;dest[9] = 0 是必须的
运行结果:
hello
Never gon
通过 strcpy 进行字符串复制时,dest 和 src 指向的内存不能重叠,否则可能产生错误。例如:
char array[10] = "abcde";
strcpy(array + 1, array, 3); // 复制
期望结果是 "aabce",而实际结果可能是 "aaaae",因为会这样复制:
flowchart TD
subgraph A["开始"]
a ~~~ b ~~~ c ~~~ d ~~~ e
end
subgraph B["array[0] 复制到 array[1]"]
B1[a] ~~~ B2[a] ~~~ B3[b] ~~~ B4[c] ~~~ B5[d]
B1 --> B2
end
subgraph C["array[1] 复制到 array[2]"]
C1[a] ~~~ C2[a] ~~~ C3[a] ~~~ C4[c] ~~~ C5[d]
C2 --> C3
end
subgraph D["array[2] 复制到 array[3]"]
D1[a] ~~~ D2[a] ~~~ D3[a] ~~~ D4[a] ~~~ D5[d]
D3 --> D4
end
A --> B --> C --> D
classDef SUB fill:#212121,color:#fefefe,stroke:#e91e63
class A SUB
class B SUB
class C SUB
class D SUB
如果要进行这样的重叠复制,请使用 memmove 函数。
编译器可能会在
strncpy进行重叠复制时纠正该问题,导致上述错误无法复现。
C17 standard (ISO/IEC 9899:2018):
7.24.2.4 The strncpy function (p: 265)
C11 standard (ISO/IEC 9899:2011):
7.24.2.4 The strncpy function (p: 363-364)
C99 standard (ISO/IEC 9899:1999):
7.21.2.4 The strncpy function (p: 326-327)
C89/C90 standard (ISO/IEC 9899:1990):
4.11.2.4 The strncpy function