Questions about C strlen function

207 views Asked by At

I tried to compare with strlen(string) with -1 but different methods gave different results:

char string[] = {"1234"};
int len = strlen(string);
int bool;
bool = -1 < strlen(string);
printf("%d",bool); //bool=0
bool = -1 < len;
printf("%d",bool); //bool=1

Assigning values to len and then comparing them gives the correct result, but I don't understand why directly comparing with strlen doesn't work.

3

There are 3 answers

2
Vlad from Moscow On BEST ANSWER

The function strlen has the unsigned return type size_t

size_t strlen(const char *s);

Usually the type size_t is an alias for the type unsigned long.

In any case the rank of the unsigned type size_t is not less than the rank of the signed type int. So due to the usual arithmetic conversion an operand of the signed type int is converted to the type size_t and if the operand of the type int has a negative value than due to propagating the sign bit it becomes a big unsigned value.

So in this expression

-1 < strlen(string)

of the type size_t (the common type of the expression) the left operand after conversion to the type size_t becomes greater than the right operand.

Consider the following demonstration program.

#include <stdio.h>

int main( void )
{
    printf( "-1 = %d\n", -1 );
    printf( "( size_t )-1 = %zu\n", ( size_t )-1 );
    return 0;
}

Its output might look like

-1 = -1
( size_t )-1 = 4294967295
6
AR7CORE On

Sign problem I guess, comparing to strlen must cast -1 to unsigned, so all bits set to 1, so whatever value is compared with, expression evaluates to 0.

While comparing with a typed variable, problem can't occur since compiler doesn't have to guess which operand has to be casted to other type.

What happens if you compile with -Wall -Wextra -Werror? Error because of comparaison between invalid types?

0
chux - Reinstate Monica On

Comparison occurs between different type pairs:

//int  size_t
  -1 < strlen(string);
//int  int
  -1 < len;

-1 < len behaves as expected as both types are the same.

With int/size_t one of the types is converted. First any type narrower than int/unsigned is promoted to int/unsigned without changing value.

Then the lower ranked type is converted to the other. size_t, some unsigned type, is very often of higher rank than int and so -1 is converted to an size_t and value by adding SIZE_MAX + 1 resulting in SIZE_MAX < strlen(string), which is false.

Should a rare implementation have size_t of a lower rank than int, the value of strlen(string) would change to type int with the same value and -1 < strlen(string) would be true.