C strlen使用指针

时间:2017-04-24 02:48:18

标签: c

我已经看到strlen的标准实现使用指针:

int strlen(char * s) {
  char *p = s;
  while (*p!='\0')
    p++;
  return p-s;
}

我得到了这个功能,但是当我尝试使用另外3种方法(现在学习指针算法)时,我想知道它们有什么问题吗?

  1. 这有点类似于本书的内容。这是错的吗?

    int strlen(char * s) {
      char *p = s;
      while (*p)
        p++;
      return p-s;
    }
    
  2. 我虽然如果我传递一个空字符串但仍然给我0,那会是错误的,有点令人困惑,因为p是预增量:(现在它返回给我5)

    int strlen(char * s) {
      char *p = s;
      while (*++p)
        ;
      return p-s;
    }
    
  3. 想出这个,后期增加并返回+1。

    int strlen(char * s) {
      char *p = s;
      while (*p++)
        ;
      return p-s;
    }
    

3 个答案:

答案 0 :(得分:1)

1)对我来说很好看。我个人更喜欢与'\ 0'进行显式比较,因此很明显你并不意味着(例如)在从上下文中不清楚的情况下将p与NULL指针进行比较。

2)程序运行时,称为堆栈的内存区域未初始化。局部变量存在于那里。你编写程序的方式是将p放入堆栈中(如果你使用const或使用malloc,它几​​乎肯定会在其他地方生活)。当你看*p时会发生什么,然后你会看到堆栈。如果字符串的长度为0,则与char p[1] = {0}相同。预递增会在\0之后立即查看字节,因此您正在查看未定义的内存。这是龙!

3)我不认为那里有一个问题:)如你所见,它总是返回一个而不是正确的答案。

附录:如果您更喜欢这种风格,也可以使用for循环编写:

size_t strlen(char * s) {
    char *p = s;
    for (; *p != '\0'; p++) {}
    return p - s;
}

或(更容易发生错误)

size_t strlen(char * s) {
    char *p = s;
    for (; *p != '\0'; p++);
    return p - s;
}

此外,strlen不能返回负数,因此您应该使用无符号值。 size_t甚至更好。

答案 1 :(得分:0)

第1版很好 - while (*p != 0)相当于while (*p),相当于p

在原始代码和版本1中,如果,指针*p会提前,且仅当 0不是p时(IOW,你不是在字符串的末尾)。

版本2和3提前*p ,无论 0是否为*p++p评估字符p指向,副作用指数*++pp评估字符p指向后的字符,并且副作用会提前p。因此,版本2和版本3将始终超过字符串末尾{{1}},这就是您的值已关闭的原因。

答案 2 :(得分:-1)

比较strlen替换函数的性能时遇到的一个问题是,与长字符串的实际strlen函数相比,它们的性能会受到影响吗?为什么? strlen在搜索字符串结尾时每次迭代处理超过一个字节。如何实现更有效的替代?

这并不困难。基本方法是查看每次迭代4个字节,并根据找到 nul-byte 的4个字节内的位置调整返回值。您可以执行以下操作(使用数组索引):

size_t strsz_idx (const char *s) {
    size_t len = 0;
    for(;;) {
        if (s[0] == 0) return len;
        if (s[1] == 0) return len + 1;
        if (s[2] == 0) return len + 2;
        if (s[3] == 0) return len + 3;
        s += 4, len += 4;
    }
}

你可以使用指针和掩码做同样的事情:

size_t strsz (const char *s) {
    size_t len = 0;
    for(;;) {
        unsigned x = *(unsigned*)s;
        if((x & 0xff) == 0) return len;
        if((x & 0xff00) == 0) return len + 1;
        if((x & 0xff0000) == 0) return len + 2;
        if((x & 0xff000000) == 0) return len + 3;
        s += 4, len += 4;
    }
}

无论哪种方式,您都会发现4字节的比较,每次迭代都会为您提供与strlen本身相当的性能。