如何有效地计算C中字符串的长度?

时间:2010-01-15 09:34:52

标签: c string performance

如何有效(及时)计算C中字符串的长度?

现在我正在做:

int calculate_length(char *string) {
    int length = 0;
    while (string[length] != '\0') {
        length++;
    }
    return length;
}

但是与strlen()相比它很慢,例如,有没有其他方法可以做到这一点?

感谢。

编辑:我在一个独立的环境中工作,我不允许使用任何外部lib,包括“string.h”。

14 个答案:

答案 0 :(得分:41)

来自FreeBSD source code

size_t
strlen(const char *str)
{
    const char *s;
    for (s = str; *s; ++s);
    return(s - str);
}

与您的代码相比,这可能很好地映射到汇编程序指令,这可以解释一个很大的性能差异。

答案 1 :(得分:9)

查看标准libc中strlen的源代码。标准库中的函数通常是高度优化的。检查出here(在汇编中编码) - 这是来自GNU libc。

size_t
DEFUN(strlen, (str), CONST char *str)
{
  int cnt;

  asm("cld\n"                   /* Search forward.  */
      /* Some old versions of gas need `repne' instead of `repnz'.  */
      "repnz\n"                 /* Look for a zero byte.  */
      "scasb" /* %0, %1, %3 */ :
      "=c" (cnt) : "D" (str), "0" (-1), "a" (0));

  return -2 - cnt;
}

答案 2 :(得分:9)

strlen()。可能的情况是,如果有人找到了更好,更快的通用方法,那么strlen就会被替换掉。

答案 3 :(得分:6)

看看GNU C library's strlen() source

它使用了许多非显而易见的技巧来提高速度而不会下降到装配,包括:

  • 找到一个正确对齐的角色
  • 将字符串中对齐的部分读入int(或更大的数据类型)以一次读取多个字符
  • 使用bit twiddling技巧检查嵌入该chars块中的其中一个字符是否为零

答案 4 :(得分:3)

最简单的方法是致电strlen()。认真。它已经由您的编译器和/或库供应商优化,以尽可能快地为您的架构。

一个常见的优化是不需要增加计数器,并从指针计算长度:

size_t my_strlen(const char *s)
{
  const char *anchor = s;

  while(*s)
   s++;

  return s - anchor;
}

答案 5 :(得分:3)

C字符串为intrinsically inefficient,使用ASCIZ约定有两个原因:

  • 标准C库使用它
  • 编译器将其用于文字字符串常量

在这种情况下,第一个是学术性的,因为您没有使用标准库,第二个可以通过创建函数或宏来轻松克服,这些函数或宏提供从C字符串到更有效的约定(如Pascal字符串)的转换。关键是如果你不使用C库,你不必成为C约定的奴隶。

答案 6 :(得分:2)

另一种加速计数的方法是使用矢量化!

以下是关于UTF8编码字符串的示例:

更快的UTF-8字符计数,

http://www.daemonology.net/blog/2008-06-05-faster-utf8-strlen.html

答案 7 :(得分:0)

在i386处理器上,libc经常使用strlen的超优化版本,通常用汇编语言编写。论文“String Length”解释了它们的工作原理。

以下是OpenBSD的一个优化版本。 (他们也有一个portable version。)这是version for the GNU libc

答案 8 :(得分:0)

上面的一些答案非常好,这是我的看法。 有一个关键字称为“注册”

#include <stdio.h>
size_t strlenNew(char *s);

int main(int argc, char* argv[])
{
    printf("Size of \"Hello World\" is ::\t%d",strlenNew("Hello World"));
    return 0;
}

size_t strlenNew(char *s)
{
    register int i=0;
    while(s[i]!='\0') i++;
    return i;
}

请在此处阅读:http://gustedt.wordpress.com/2010/08/17/a-common-misconsception-the-register-keyword/http://msdn.microsoft.com/en-us/library/482s4fy9(v=vs.80).aspx

从第一个链接:

  

这对数组变量特别有用。数组变量   容易与指针变量混淆。除非紧随其后   a [expr]或sizeof,它的计算结果为第一个地址   元件。如果声明数组寄存器,则所有这些用途都是   禁止;我们只访问个别元素或询问总数   尺寸。这样的寄存器阵列可以更容易地使用,就像它一样   只是优化器的一组变量。没有别名(访问   可能会出现相同的变量通过不同的指针。

因此,有时可能存在性能波动。就个人而言,这是我最喜欢的实现之一,但Sudhanshu和Andomar也提供了一个很好的实现:)

答案 9 :(得分:0)

我有同样的问题,我解决了。关键是for循环的第二个条件:

int longitud(char cad[]){

    int i, cont;

    cont = 0;

    for(i = 0; i < 30 && cad[i] != '\0'; i++){
        if(cad[i] != '\0'){
            if(cad[i] != ' '){
                cont++;
            }
        }
    }
    cont--;
    return cont;
}

答案 10 :(得分:0)

我没有找到更好的:

  

内联   size_t mystrlen(char * _)

  { return ((_ == NULL) ? (_[0] != '\0')) ? 0 : (1 + mystrlen(_ + 1)); }

答案 11 :(得分:0)

用于计算字符串长度的基本C程序。

#include <stdio.h>

/**
* Method to calculate string length.
* Returns -1 in case of null pointer, else return string length.
**/
int length(char *str) {

    int i = -1;
    // Check for NULL pointer, then return i = -1;
    if(str == NULL) return i;

    // Iterate till the empty character.
    while (str[++i] != '\0');
    return i;  // Return string length.
}

int main (int argc, char **argv) {

    int len = 0;
    char abc[] = "hello";
    len = length(abc);
    printf("%d", len);  
    return 0;
}
  

注意:为了更好的方法,我们应该始终将数组大小传递给函数以避免内存泄漏。例如,方法的**原型应该是*:*

/**
* @desc calculate the length of str.
* @param1 *str pointer to base address of char array.
* @param2 size = capacity of str to hold characters.
* @return int -1 in case of NULL, else return string length.
**/
int length (char *str, int size);

答案 12 :(得分:-1)

我不太确定你想做什么。

您想重新编写strlen以使您的代码与标准c-Library兼容,或者您​​想要管理字符串。

在第一种情况下,我认为你最好直接使用标准库。

另一个案例很有意思:你应该看看c ++字符串类,它具有traits策略的实现(允许快速操作非常大的字符串)。

答案 13 :(得分:-5)

int max;
max = sizeof(str);
return (--max);