strcpy和stpcpy有什么区别?

在阅读strcpy的手册页时,我发现函数stpcpy也存在。 但是,我在手册页中注意到的唯一区别是:

 char * stpcpy(char *s1, const char *s2); char * strcpy(char *restrict s1, const char *restrict s2); 

那么, restrict在这里意味着什么?

restrict告诉编译器s1s2指向不同的数组,并且指向数组中没有重叠。 在某些情况下,这可能允许编译器执行额外的优化(即,它可能复制多个字符的块而不必检查重叠)。

另请注意,返回值是不同的: 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); 

当然值得一提的是strcpystrcat是标准函数,而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)。