如何strcpy和返回复制的字符数

How to strcpy and return number of copied characters?

本文关键字:字符 复制 返回 strcpy 如何      更新时间:2023-10-16

我想将一个以null结尾的字符串复制到另一个位置,并想知道复制的字符串有多长。效率至关重要。有一个strcpy函数可以实现这一点,但它不返回实际复制了多少个字符。

当然,我可以通过稍后简单地调用strlen来检测复制字符串的长度来找到这一点,但这意味着第二次遍历字符串中的字符,尽管strcpy无论如何都必须跟踪它复制了多少个字符。出于性能原因,我不希望进行这样的第二次遍历。

我知道用一个简单的逐字符副本编写自己的strcpy很容易,但我认为标准库可能会应用魔术,使strcpy比简单的逐个字符实现更快。

那么,对于strcpy,在不再次遍历字符串的情况下接收复制的字符数的最佳方法是什么?

许多系统支持stpcpy,它返回指向目的地末尾的指针。您可以减去原始的目标指针,这样就可以得到长度。

我会使用sprintf来完成这项工作:

size_t len_strcpy(char *dest, char const *src) { 
    return sprintf("%s", dest, src);
}

不过,很难猜测这是否真的会比使用strcpystrlen慢或快。例如,对于微软编译器,他们最近在sprintf等的实现方面做了一些工作,因此(在英特尔上)它使用矢量指令,运行速度非常快。使用旧版本的编译器,strcpy/strlen获胜的几率会大得多。

如果你真的需要这个,那么写自己的会很容易

unsigned int lenstrcpy(char dest[], const char source[]) {
    unsigned int i = 0;
    while ((dest[i] = source[i]) != '') {
       i++;
    }
    return i; 
}

这是一个活生生的例子。

我会尝试使用strlen(),然后使用memcpy(),但像往常一样,当速度是你的目标时,你最好针对目标平台进行测试,因为理论上可能有很多因素难以统计。

memcpy()添加到Ben的速度测试中

关于gcc 5.1.0与-O1的结果是:

  • 第1部分:62181-手册副本
  • 第2部分:195093-strcpy/strlen
  • 第3部分:45568-strlen/memcpy

第1部分和第3部分的-O2结果几乎没有变化,但第2部分发生了戏剧性的变化:

  • 第1部分:62234
  • 第2部分:12129
  • 第3部分:45565

看起来O2优化编译器消除了对strlen()的额外调用,并使用了缓存值。

标准C库不提供您想要的函数,因此您需要编写自己的函数。幸运的是,它并不太复杂:

size_t StrCpyLen(char *dest, const char *src) {
    const char *s = src;
    while ((*dest++ = *s++))
        ;
    return s - src - 1;
}

演示。

上面的实现是从K&R、 有一个小的修改:它不是直接使用src,而是在运行循环之前进行复制,这样一旦循环完成,就可以通过减去原始src来确定长度。