'C: Custom strlen() library function

I created my version of strlen() function.

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

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

    return i;
}

It gives me correct output everytime i run.But my collegues are saying this code may cause problem on systems where length of character is greater than 1 byte. Is that so ??

So they modified the code as following:

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

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

    return p - start;
}

I always thought in C a character is 1 byte long.

Is former snippet is better than the latter or vice versa ??



Solution 1:[1]

It is guaranteed in C that sizeof(char) is 1, so you are right.

To add some authenticity, directly quoting C11, chapter ยง6.5.3.4, The sizeof and _Alignof operators

When sizeof is applied to an operand that has type char, unsigned char, or signed char, (or a qualified version thereof) the result is 1. [....]

That said, pointer arithmetic honors the data type, so the second approach does not make any sense in the respect of what is is expected to do, anyway. Both the case, you're operating on p, which is char*, so the effect will be the same.

Solution 2:[2]

As you use p++, you increment you pointer by sizeof(char). Hence, it's not relevant what is sizeof(char) even if it was variable between different machines. Your colleagues are wrong.

Note: If you want to count the bytes, and not the characters, then your colleagues could be correct (if char was not guaranteed to be 1 byte, but it is). If you want to count the characters, then your colleagues are just wrong at all.

Solution 3:[3]

OP posted "length of character is greater than 1 byte", not char. OP is right when one limits a character to only char, signed char, unsigned char. Those 3 always have a size of 1.

OP's colleagues may not all think in that restrictive sense. The C spec has many character types: single-byte character, multibyte character, extended character, wide character, not all 1 byte.

Modified code has weakness. It does not sensible relate to "length of character is greater than 1 byte". Also, the i++; is pointless. The return type of unsigned maybe insufficient. Use size_t for an unsigned type that is neither too wide nor narrow.

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

Is former snippet is better than the latter or vice versa ??

Neither returns a type that will not overflow.

Solution 4:[4]

Although the others answered your question regarding the character size, your version is still not correct.

The current standard (ISO/IEC 9899:2011) is short and precise here:

7.24.6.3 The strlen function

Synopsis

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

Description

2 The strlen function computes the length of the string pointed to by s.

Returns

3 The strlen function returns the number of characters that precede the terminating null character.

So a fully compliant function would be

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

The main difference is that it checks the input (could be NULL, but e.g.: glibc's strlen segfaults. If you want it to segfault, strip the test for s == NULL in the loop. Segfaulting is probably the better alternative, otherwise you get the sort of bugs we like to call "Heisenbugs". Bugs that tend to disappear when you look at them and their waveform collapses) and uses size_t as the output.

The Glibc version handles several bytes at once if and when possible--don't know if such an optimization is useful.

If you want the equivalent of wsclen() you can do something like that:

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

Counting multibyte characters (mbrlen() checks for one character only, but you can use mbrtowc()) is quite complicated and out of the scope of this short post.

Solution 5:[5]

strlen function using for:

size_t my_strlen(const char *s) {

    size_t n;

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

Or:

size_t n;

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

Or:

size_t n;

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

Or:

size_t n;

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

Or:

size_t n = 0;
int i;

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

Solution 6:[6]

I think this is quite nice too.

unsigned int StrLen(const char* String)
{
    unsigned int Counter;
    for (Counter = 0; String[Counter] != '\0'; Counter++);
    return Counter;
}

It just makes a loop until the counter reaches the null character, and increments the counter.

Solution 7:[7]

In terms of Pointer arithmetic, It is not going to give you different result on platform having char as 2 bytes long as you are working on pointers and pointer arithmetic always stick to data types. Here is another way of finding string len, which do not use pointer airthmetic-

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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 SomethingSomething
Solution 3
Solution 4 deamentiaemundi
Solution 5
Solution 6 triangleBoi
Solution 7