Estoy analizando un escenario:
char str[] = ""; // Understand Si entiendo strlen(str) , resulta ser 0. Esto está bien.
printf(" %d, %ul, %u, %d, %ul, %u", strlen(str), strlen(str), strlen(str), strlen(str) - 1, strlen(str) - 1, strlen(str) - 1);La salida es:
0, 0l, 0, -1, 4294967295l, 4294967295
Estos también los entiendo.
for (int i = 0; i < strlen(str) - 1; i++) { } Aquí no entiendo cuál sería el valor de strlen(str) - 1 en la condición for .
strlen(str) - 1 da el valor 4294967295 en el bucle for. ¿Porqué es eso? ¿Por qué no -1?
strlen devuelve size_t que es un entero sin signo. Entonces strlen(str)-1 produciría SIZE_MAX (el valor máximo que puede contener size_t ) si strlen(str) es 0 .
Debería usar %zu para imprimir valores de size_t .
Esta declaración
printf(" %d, %ul, %u, %d, %ul, %u", strlen(str),strlen(str),strlen(str),strlen(str)-1,strlen(str)-1,strlen(str)-1); muestra que cuando strlen( str ) - 1 se genera como un entero sin signo, por ejemplo, utilizando el especificador de formato %ul , su valor es 4294967295l
En la condición del bucle.
for (int i=0;i<strlen(str)-1;i++)el compilador tiene que determinar el tipo común de los operandos izquierdo y derecho para determinar el tipo del resultado de la condición
i<strlen(str)-1 El operando derecho strlen(str)-1 tiene el tipo size_t (el tipo de retorno de la función strlen es size_t ). Por lo general, es un tipo entero sin signo que corresponde a unsigned long . No puede tener valores negativos. Cualquier valor almacenado en un objeto de este tipo se interpreta como un valor no negativo y, como muestra la salida, el valor de strlen(str)-1 es igual a 4294967295l . (El valor real que podría obtener si usara el especificador de tipo %zu porque no se puede excluir que size_t pueda corresponder incluso a unsigned long long)
El operando derecho tiene tipo int . Su rango es al menos no mayor que el rango de size_type. Entonces, ambos operandos se convierten al tipo size_t y tienen valores no negativos.
Este procedimiento de determinación del tipo común se denomina conversión aritmética habitual. Es obvio que 4294967295l es mayor que 0. Por lo tanto, el ciclo iterará 4294967295l veces si no tiene una instrucción break.
Podría obtener el resultado esperado si reescribe la condición en el ciclo de la siguiente manera
for ( int i = 0; i < ( int )strlen( str ) - 1; i++ )