strcpy和stpcpy有什么区别?
在阅读strcpy
的手册页时,我发现函数stpcpy
也存在。 但是,我在手册页中注意到的唯一区别是:
char * stpcpy(char *s1, const char *s2); char * strcpy(char *restrict s1, const char *restrict s2);
那么, restrict
在这里意味着什么?
restrict
告诉编译器s1
和s2
指向不同的数组,并且指向数组中没有重叠。 在某些情况下,这可能允许编译器执行额外的优化(即,它可能复制多个字符的块而不必检查重叠)。
另请注意,返回值是不同的: stpcpy
返回指向复制到目标缓冲区的\0
的指针,而strcpy
返回指向字符串开头的指针(实际上它return s1;
)。
你在标题中提出的问题和关于restrict
的问题实际上是两个完全不相关的问题。 其他答案已经为您提供了一些很好的链接,可以帮助您了解有关restrict
更多信息。
但是,这两个function的主要区别并不在于restrict
说明符。 事实上,在C语言规范的C99版本中, strcpy
也对其参数进行了restrict
。 您在strcpy
的手册页上看到的内容根本不会更新以符合C99。
主要区别(您似乎错过了)是stpcpy
的返回值。 stpcpy
返回指向目标字符串的终止\0
字符的指针。 这立即明确了stpcpy
的目的及其存在背后的基本原理:当您需要将多个子字符串连接成一个字符串时,此函数旨在用作strcat
函数的智能替代。 你看, strcat
在这样的应用程序中运行得很差(我甚至说strcat
在实际代码中没有任何有意义的用途)。 strcat
的问题在于它每次向其添加内容时都会重新扫描目标字符串,因此会执行大量不必要的工作,并且基本上会产生比光更多的热量。 例如,以下代码遇到了这个问题
const char *part1, *part2, *part3, *part4; ... char buffer[size]; /* assume that `size` is calculated properly */ strcpy(buffer, part1); strcat(buffer, part2); strcat(buffer, part3); strcat(buffer, part4);
可以使用stpcpy
以更合理的方式重新实现此代码
stpcpy(stpcpy(stpcpy(stpcpy(buffer, part1), part2), part3), part4);
如果您不喜欢链式调用,则可以使用中间指针来存储中间stpcpy
调用的返回值
char *end = buffer; end = stpcpy(end, part1); end = stpcpy(end, part2); end = stpcpy(end, part3); end = stpcpy(end, part4);
当然值得一提的是strcpy
和strcat
是标准函数,而stpcpy
则不是。
维基百科条目restrict
简而言之, restrict
告诉编译器s1和s2指向的内存段不重叠; 这允许代码执行较少的错误检查。
stpcpy()
函数将src指向的字符串(包括终止'\0'
字符)复制到dest指向的数组。 字符串可能不重叠,目标字符串dest必须足够大才能接收副本。
这满足了restrict
的要求,即使它不在函数签名中。 如果存在C99,则可以添加。
stpcpy()
返回指向字符串dest结尾的指针(即终止空字节的地址)而不是开头。
这使您可以更轻松,更有效地连接多个字符串,因为src
可以“粘贴”到从最后一个stpcpy()
返回的指针上。 替代方案的天真实现, strcat
必须在开始复制之前找到dest
字符串的末尾。
请注意以下事项:
此函数不是C或POSIX.1标准的一部分,在Unix系统上不是惯用的,但也不是GNU发明。 也许它来自MS-DOS。 如今,它也出现在BSD上。
另一个区别是返回值。 从手册页:“strcpy()和strncpy()函数返回s1。stpcpy()函数返回指向s1的终止’\ 0’字符的指针。”
strcpy返回s1但stpcpy返回s1 + strlen(s2)。