繁体   English   中英

C: 自定义 strlen() 库函数

[英]C: Custom strlen() library function

我创建了我的strlen()函数版本。

unsigned int my_strlen(char *p)
{
    unsigned int i = 0;

    while(*p!='\0')
    {
        i++;
        p++;
    }

    return i;
}

每次运行时它都会给我正确的输出。但是我的同事说这段代码可能会导致字符长度大于1 byte系统出现问题。 是这样吗??

所以他们修改了代码如下:

unsigned int my_strlen(char *p)
{
    unsigned int i = 0;
    char *start = p;

    while(*p!='\0')
    {
        i++;
        p++;
    }

    return p - start;
}

我一直认为在 C 中一个字符是 1 个字节长。

前一个片段比后者好还是反之亦然??

在 C 中保证sizeof(char)为 1,所以你是对的。

为了增加一些真实性,直接引用C11 ,章节 §6.5.3.4, sizeof_Alignof运算符

sizeof应用于具有charunsigned charsigned char类型(或其限定版本)的操作数时,结果为 1。 [....]

也就是说,指针算术尊重数据类型,所以无论如何,第二种方法在预期做什么方面没有任何意义。 在这两种情况下,您都在p操作,即char* ,因此效果是相同的。

当您使用p++ ,您将指针增加sizeof(char) 因此,即使sizeof(char)在不同机器之间是可变的,它也无关紧要。 你的同事错了。

注意:如果你想计算字节数,而不是字符数,那么你的同事可能是正确的(如果不能保证 char 是 1 个字节,但它确实是)。 如果你要数字,那你的同事根本就错了。

尽管其他人回答了您有关字符大小的问题,但您的版本仍然不正确。

当前的标准 (ISO/IEC 9899:2011) 在这里简短而准确:

7.24.6.3 strlen函数

概要

 #include <string.h>`<br> size_t strlen(const char *s);

说明

2 strlen函数计算 s 指向的字符串的长度。

退货

3 strlen函数返回终止空字符之前的字符数。

所以一个完全兼容的函数将是

size_t stringlength(const char *s){
  size_t i = 0;
  while(s && *s != '\0'){
      s++;
      i++;
  }
  return i;
}

主要区别在于它检查输入(可能是NULL ,但例如:glibc 的strlen segfaults。如果您希望它进行 segfault,请在循环中去除s == NULL的测试。Segfaulting 可能是更好的选择,否则您会得到那种我们喜欢称之为“Heisenbugs”的错误。当你查看它们并且它们的波形崩溃时往往会消失的错误)并使用size_t作为输出。

Glibc 版本在可能的情况下一次处理多个字节——不知道这样的优化是否有用。

如果你想要等效的wsclen()你可以做这样的事情:

#include <wchar.h>
size_t wstringlength(const wchar_t *s){
  size_t i = 0;
  while(s[i] != L'\0'){
      i++;
  }
  return i;
}

计算多字节字符( mbrlen()检查一个字符,但您可以使用mbrtowc() )非常复杂,超出了这篇短文的范围。

OP 发布了“字符长度大于 1 个字节”,而不是char 当将字符限制为仅charsigned charunsigned char时,OP 是正确的。 这 3 个总是大小为 1。

OP 的同事可能并非都以这种限制性的方式思考。 C 规范有许多字符类型:单字节字符多字节字符扩展字符宽字符,并非都是 1 字节。

修改后的代码有弱点。 它与“字符长度大于 1 个字节”无关。 另外, i++; 毫无意义。 unsigned的返回类型可能不够。 size_t用于既不太宽也不太窄的无符号类型。

// simplify
size_t my_strlen2(const char *p) {
    const char *start = p;
    while(*p) p++;
    return (size_t) (p - start);
}

前一个片段比后者好还是反之亦然??

两者都不返回不会溢出的类型。

使用for strlen函数:

size_t my_strlen(const char *s) {

    size_t n;

    for (n = 0; *s; s++)
        n++;
    return n;
}

或者:

size_t n;

for (n = 0; *s != '\0'; s++)
    n++;
return n;

或者:

size_t n;

for (n = 0; *(s++); )
    n++;
return n;

或者:

size_t n;

for (n = 0; *s; n++)
    s++;
return n;

或者:

size_t n = 0;
int i;

for (i = 0; s[i]; i++)
    n++;
return n;

在指针算术方面,只要您处理指针和指针算术始终坚持数据类型,它就不会在具有 char 为 2 个字节的平台上给您不同的结果。 这是另一种查找字符串 len 的方法,它不使用指针 airthmetic-

int len  = -1;
while(p[++len] != '\0');
return len;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM