0%

如何正确拷贝字符串

  • strcpy
  • strncpy
  • memcpy
  • snprintf
  • strlen
  • sizeof

正确无隐患拷贝字符串

strlen

strlen 运行时计算字符串长度,当字符数组中不存在 \0 时,计算错误

sizeof

sizeof 编译时计算分配空间,字符数组大小

strcpy

    char *strcpy(char *dest, const char *src);

strcpy 提供字符串的复制,只用于字符串复制,会复制字符串的结束符。不需要指定长度,它遇到被复制字符的串结束符 \0 才结束,所以容易溢出

strncpy

    char *strncpy(char *dest, const char *src, size_t n);

strncpy 把src所指由 \0 结束的字符串的前n个字节复制到dest所指的数组中

  • 如果src的前n个字节不含 \0 字符,则结果不会以 \0 字符结束,对dest进行字符串运行会导致出错
  • 如果src的长度小于n个字节,则以 \0 填充dest直到复制完n个字节,效率低下
  • src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串

strncpy 正确用法

// solution A
char dest[MAX];
strncpy(dest, src, sizeof(dest)-1);
dest[MAX-1] = '\0';

// solution B
char dest[MAX];
memset(dest, 0, sizeof(dest));
strncpy(dest, src, sizeof(dest)-1);

正确用法

  • 通用用法:snprintf
  • 性能用法:memcpy

snprintf

int snprintf(char *str, size_t size, const char *format, ...);

使用 snprintf 进行字符串拷贝,防止溢出,snprintf 会把buf的最后一个位置保留为 \0

snprintf(dest, sizeof(dest), "%s", src);

当 src 长度远大于 dest 时,由于 snprintf 要返回 src 的字节数,需要扫描 src,会产生性能损失

memcpy

void *memcpy(void *dest, const void *src, size_t n);

memcpy 提供了一般内存的复制,对于需要复制的内容没有限制。需要考虑字符串拷贝性能时使用 strlen + memcpy