在C中复制字符串中获取null char的最快方法

lor*_*ova 4 c string performance crt

我需要获取指向字符串的终止空字符的指针.

目前我正在使用这种简单的方式:MyString + strlen(MyString)这可能是非常好的脱离上下文.

但是我对这个解决方案感到不舒服,因为我必须在字符串复制之后这样做:

char MyString[32];
char* EndOfString;
strcpy(MyString, "Foo");
EndOfString = MyString + strlen(MyString);
Run Code Online (Sandbox Code Playgroud)

所以我在字符串周围循环两次,第一次进入strcpy,第二次进入strlen.

我想通过返回复制字符数的自定义函数来避免这种开销:

size_t strcpylen(char *strDestination, const char *strSource)
{
    size_t len = 0;
    while( *strDestination++ = *strSource++ )
        len++;
    return len;
}

EndOfString = MyString + strcpylen(MyString, "Foobar");
Run Code Online (Sandbox Code Playgroud)

但是,我担心我的实现可能比编译器提供的CRT函数慢(可能使用一些程序集优化或其他技巧而不是简单的char-by-char循环).或者我可能不知道一些标准的内置功能已经做到了吗?


我做了一些可怜的男人标杆,迭代0x1FFFFFFF倍三种算法(strcpy+ strlen,我的版本strcpylen,以及版本user434507).结果是:

1)strcpy+ strlen是胜利者,只有967毫秒;

2)我的版本需要更多:57秒!

3)编辑版需要53秒.

因此,在我的环境中使用两个CRT功能而不是自定义"优化"版本的速度要快50倍!

Eug*_*ith 5

size_t strcpylen(char *strDestination, const char *strSource)
{
    char* dest = strDestination;
    while( *dest++ = *strSource++ );
    return dest - strDestination;
}
Run Code Online (Sandbox Code Playgroud)

这几乎就是strcpy的CRT版本所做的,除了CRT版本也会做一些检查,例如确保两个参数都是非null.

编辑:我正在查看VC++ 2005的CRT源代码.pmg是正确的,没有检查.strcpy有两个版本.一个用汇编语言编写,另一个用C语言编写.这是C版本:

char * __cdecl strcpy(char * dst, const char * src)
{
        char * cp = dst;

        while( *cp++ = *src++ )
                ;               /* Copy src over dst */

        return( dst );
}
Run Code Online (Sandbox Code Playgroud)

  • VC2005汇编版本一次执行4个字节,并通过对齐源指针开始.您不能在dword中间拥有数据段边框. (3认同)
  • @Lorenzo:在写之前你会检查你刚读过的8块中是否有0字节.如果没有,则写入所有8个字节.如果是这样,你几乎完成了,你分支到一些代码,一次写一个剩余的几个字节.我没有MS代码可以看,顺便说一下,我只是说它是如何*可以*完成的.实际上,像MS这样的声音是4,而不是8. (3认同)
  • 我相信`strcpy`不会验证它的输入(如果其中一个参数为NULL,则它是未定义的行为),并且库可以复制为8个字节的组,例如. (2认同)
  • @Lorenzo:我认为SSE中有,或者至少你可以在很多指令中快速完成.即使在没有的CPU上,一次读取一个对齐的字通常比一次读取一个字节的速度更快,因此至少有一个潜在的增益. (2认同)

Der*_*unk 5

Hacker's Delight有一个很好的部分,可以找到C字符串中的第一个空字节(参见第6章第1节).我在Google Books中找到了(部分)它,代码似乎就在这里.我总是回到这本书.希望它有用.