4

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

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

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

char MyString[32];
char* EndOfString;
strcpy(MyString, "Foo");
EndOfString = MyString + strlen(MyString);

所以我在字符串周围循环了两次,第一次是 in 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");

但是,我担心我的实现可能比编译器提供的 CRT 函数慢(可能使用一些汇编优化或其他技巧,而不是简单的逐字符循环)。或者,也许我不知道一些标准的内置函数已经这样做了?


我做了一些穷人基准测试,迭代 0x1FFFFFFF 乘以三个算法(strcpy+ strlen,我的版本和user434507strcpylen版本)。结果是:

1) strcpy+strlen是赢家,只有 967 毫秒;

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

3) 编辑后的版本耗时 53 秒。

因此,在我的环境中使用两个 CRT 函数而不是自定义“优化”版本快 50 倍以上!

4

8 回答 8

5
size_t strcpylen(char *strDestination, const char *strSource)
{
    char* dest = strDestination;
    while( *dest++ = *strSource++ );
    return dest - strDestination;
}

This is almost exactly what the CRT version of strcpy does, except that the CRT version will also do some checking e.g. to make sure that both arguments are non-null.

Edit: I'm looking at the CRT source for VC++ 2005. pmg is correct, there's no checking. There are two versions of strcpy. One is written in assembly, the other in C. Here's the C version:

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

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

        return( dst );
}
于 2010-11-13T14:20:56.293 回答
5

Hacker's Delight中有一个很好的部分介绍了如何在 C 字符串中查找第一个空字节(参见第 6 章第 1 部分)。我在Google Books中找到(部分)它,代码似乎在这里。我总是回到这本书。希望它有帮助。

于 2010-11-13T14:32:03.437 回答
1

Use strlcpy(), which will return the length of what it copied (assuming your size parameter is large enough).

于 2010-11-13T14:18:04.717 回答
1

你可以试试这个:

int len = strlen(new_str);
memcpy(MyString, new_str, len + 1);
EndOfString = MyString + len;

只有当它很大时才有意义new_str,因为memcpy它比标准方法快得多while( *dest++ = *strSource++ );,但有额外的初始化成本。

于 2010-11-13T15:07:28.877 回答
1

只是几点说明:如果您的函数不经常被调用,那么它可能从您的代码中运行得比从 C 库中运行得更快,因为您的代码已经在 CPU 缓存中。

您的基准测试正在做的是确保库调用在缓存中,而在实际应用程序中不一定是这种情况。

此外,内联甚至可以节省更多周期:编译器和 CPU 更喜欢叶函数调用(一级封装而不是多个调用级别)用于分支预测和数据预取。

这完全取决于您的代码风格、您的应用程序以及您需要节省周期的地方。

如您所见,这张照片比之前曝光的要复杂一些。

于 2010-12-19T17:32:45.360 回答
0

I think you may be worrying unnecessarily here. It's likely that any possible gain you can make here would be more than offset by better improvements you can make elsewhere. My advice would be not to worry about this, get your code finished and see whether you are so short of processing cycles that the benefit of this optimisation outweighs the additional work and future maintenance effort to speed it up.

In short: don't do it.

于 2010-11-13T14:22:01.317 回答
0

尝试memccpy()(或_memccpy()在 VC 2005+ 中)。我针对它strcpy + strlen和您的自定义算法进行了一些测试,在我的环境中它击败了两者。不过,我不知道它在您的算法中的效果如何,因为对我而言,您的算法运行速度比您看到的要快得多,而且strcpy + strlen速度要慢得多(前者为 14.4 秒,后者为 7.3 秒,使用您的迭代次数) . 我在大约 5 秒时记录了下面的代码。

int main(int argc, char *argv[])
{
    char test_string[] = "Foo";
    char new_string[64];
    char *null_character = NULL;
    int i;
    int iterations = 0x1FFFFFFF;

    for(i = 0; i < iterations; i++)
    {
        null_character = memccpy(new_string, test_string, 0, 64);
        --null_character;
    }

    return 0;
}
于 2010-11-14T07:01:43.267 回答
-2

Check out sprintf.
http://www.cplusplus.com/reference/clibrary/cstdio/sprintf/

于 2010-11-13T14:13:30.620 回答