BioCoder
BioCoder

Reputation: 605

Why C function strlen() returns a wrong length of a char?

My C codes are listed below:

char s="MIDSH"[3];
printf("%d\n",strlen(&s));

The result of running is 2, which is wrong because char s is just an 'S'.

Does anybody know why and how to solve this problem?

Upvotes: 0

Views: 5601

Answers (6)

DragonLord
DragonLord

Reputation: 6641

Constant string "MIDSH" has an invisible terminating \0 at the end, so it's actually MIDSH0.

[3] returns the fourth item in a 0-based array.

What happens next is dependent on the compiler, and the difference between "equal" (EQUAL in Lisp) and "identical" (EQ in Lisp). Normally the single char s will be a distinct memory location. The contents of 'S' will get copied into s, as an equal but distinct value. Then, when you take the address of variable char s with an &s, and feed it to strlen, strlen will keep looking in the next whatever memory locations after that single char s until it finds a 0 byte, and then return that length to you. This is completely undefined, and could result in an out-of-bounds memory segfault.

However, in this very unusual case, it looks like if you're using an optimizing compiler and no other computations are done on this. Apparently, instead of creating a new memory location the compiler got lazy and simply assigned the address of the fourth character to variable char s. In this case, char s is identical to the fourth char. Then, when taking the address of s, you got the address of the fourth char, S. Taking the address of this and feeding it to strlen, you get SH0; the 0 doesn't count in the length, so you come up with an answer of 2.

This is extremely unexpected and serendipitous behavior. It is much better to code using string pointers yourself, char *p = mystring+3; strlen(p); , instead of attempting to take the address of a single char variable then interpret it as a string.

Upvotes: -1

haccks
haccks

Reputation: 106112

The statement

printf("%d\n",strlen(&s));  

make no sense for the given case. strlen expects a null terminating string, s is of char type and &s need not necessarily point to an string. What you are getting is one the result of undefined behavior of the program.

To get the size of s you can use sizeof operator

printf("%zu\n", sizeof(s)); 

Upvotes: 6

RockDeria
RockDeria

Reputation: 23

when you use "char s=" you create a new address on the stack for 's',and this address can't be add or reduce!so though you give strlen a char* but it can't find '\0' by add address.All is wrong. you should use strlen with a address for char which is a array.like:

char* s = "MIDSH";
printf("%d\n", strlen(s)); //print 5
s++;
printf("%d\n", strlen(s)); //print 4

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409452

The strlen function treats its argument as a pointer to a sequence of characters, where the sequence is terminated by the '\0' character.

By passing a pointer to the single character variable s you effectively say that &s is the first character in such a sequence, but it's not. That means strlen will continue to search in memory under false premises and you will have undefined behavior.

Upvotes: 4

That's actually quite an interesting question. Let's break it up:

"MIDSH"[3]

String literals have array types. So the above applies the subscript operator to the array and evaluates to the 4th character 'S'. It then assigns it to the single character variable s.

printf("%d\n",strlen(&s));

Since s is a single character, and not part of an actual string, the behavior is undefined for the above code.

Upvotes: 11

Mohit Jain
Mohit Jain

Reputation: 30489

Signature of strlen is:

size_t strlen(const char *s);
/* The strlen() function calculates the
   length of the string s, excluding the
   terminating null byte ('\0'). */

strlen expects the input const char array is null terminated. But when you pass the address of an auto variable, you can't guarantee this and thus your program has an undefined behavior.

Does anybody know why and how to solve this problem?

sizeof(char) is guaranteed to be 1. So use sizeof or 1.

Upvotes: 8

Related Questions