簡體   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