这可能有点毫无意义,但我很好奇你们对它的看法。我正在使用指针迭代一个字符串,并希望从中拉出一个短子串(将子字符串放入预先分配的临时数组)。是否有任何理由在strncopy上使用赋值,反之亦然?即
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{ char orig[] = "Hello. I am looking for Molly.";
/* Strings to store the copies
* Pretend that strings had some prior value, ensure null-termination */
char cpy1[4] = "huh\0";
char cpy2[4] = "huh\0";
/* Pointer to simulate iteration over a string */
char *startptr = orig + 2;
int length = 3;
int i;
/* Using strncopy */
strncpy(cpy1, startptr, length);
/* Using assignment operator */
for (i = 0; i < length; i++)
{ cpy2[i] = *(startptr + i);
}
/* Display Results */
printf("strncpy result:\n");
printf("%s\n\n", cpy1);
printf("loop result:\n");
printf("%s\n", cpy2);
}
在我看来,strncopy更少打字,更容易阅读,但我看到人们主张循环。有区别吗?它甚至重要吗?假设这是针对i的小值(0
参考:Strings in c, how to get subString,How to get substring in C,Difference between strncpy and memcpy?
答案 0 :(得分:4)
strncpy(char * dst, char *src, size_t len)
有两个特殊的属性:
(strlen(src) >= len)
:结果字符串不会以空字符结尾。(strlen(src) < len)
:字符串的结尾将填充/填充'\ 0'。第一个属性会强制您实际检查(strlen(src) >= len)
是否合适。 (或者用dst[len-1] = '\0';
粗暴地将最终字符设置为nul,就像上面的@Gilles所做的那样)另一个属性并不特别危险,但可能会溢出很多周期。想象:
char buff[10000];
strncpy(buff, "Hello!", sizeof buff);
触及10000个字节,其中只需要触摸7个字节。
我的建议:
memcpy(dst,src,len); dst[len] = 0;
由于安全操作,strncpy()版本已经需要知道大小(以及对它们的检查!),memcpy()版本并不比strncpy()版本更复杂或更危险。 (从技术上讲,它甚至更快;因为memcpy()不必检查'\ 0'字节)
答案 1 :(得分:3)
虽然这看似违反直觉,但是复制字符串比使用循环中的赋值运算符有更多优化方法。例如,IA-32为REP
,MOVS
,STOS
等提供CMPS
前缀用于字符串处理,这些可以比复制一个char的循环快得多一次。 strncpy
或strcpy
的实施可能会选择使用此类硬件优化代码来实现更好的性能。
答案 2 :(得分:1)
只要您知道自己的长度在“范围内”并且所有内容都已正确终止,那么strncpy
会更好。
如果你需要在那里进行长度检查等,循环可能会更方便。
答案 3 :(得分:0)
分配循环是一个坏主意,因为你正在重新发明轮子。您可能会犯错误,并且您的代码可能不如标准库中的代码有效(某些处理器已经优化了内存副本的指令,并且优化的实现通常至少可以逐字复制)。
但是,请注意strncpy
不是一个圆润的轮子。特别是,如果字符串太长,则不会向目标附加空字节。 BSD函数strlcpy
设计得更好,但并不是随处可用。甚至strlcpy
is not a panacea:您需要正确获取缓冲区大小,并注意它可能会截断字符串。
复制字符串的可移植方法是,如果字符串太长则截断,是调用strncpy
并始终添加终止空字节。如果缓冲区是一个数组:
char buffer[BUFFER_SIZE];
strncpy(buffer, source, sizeof(buffer)-1);
buf[sizeof(buffer)-1] = 0;
如果缓冲区由指针和大小给出:
strncpy(buf, source, buffer_size-1);
buf[buffer_size-1] = 0;