Estoy tratando de reimplementar la strcasecmpfunción en C y noté lo que parece ser una inconsistencia en el proceso de comparación.
Desde man strcmp
La función strcmp () compara las dos cadenas s1 y s2. La configuración regional no se tiene en cuenta (para una comparación de configuración regional, consulte strcoll (3)). Devuelve un número entero menor, igual o mayor que cero si se encuentra s1, respectivamente, menor que, para que coincida o mayor que s2.
Desde man strcasecmp
La función strcasecmp () realiza una comparación byte por byte de las cadenas s1 y s2, ignorando el caso de los caracteres. Devuelve un número entero menor, igual o mayor que cero si se encuentra s1, respectivamente, menor que, para que coincida o mayor que s2.
int strcmp(const char *s1, const char *s2);
int strcasecmp(const char *s1, const char *s2);
Dada esta información, no entiendo el resultado del siguiente código:
#include <stdio.h>
#include <string.h>
int main()
{
    // ASCII values
    // 'A' = 65
    // '_' = 95
    // 'a' = 97
    printf("%i\n", strcmp("A", "_"));
    printf("%i\n", strcmp("a", "_"));
    printf("%i\n", strcasecmp("A", "_"));
    printf("%i\n", strcasecmp("a", "_"));
    return 0;
}
Ouput:
-1  # "A" is less than "_"
1   # "a" is more than "_"
2   # "A" is more than "_" with strcasecmp ???
2   # "a" is more than "_" with strcasecmp
Parece que, si el carácter actual en s1es una letra, siempre se convierte en minúsculas, independientemente de si el carácter actual en s2es una letra o no.
¿Alguien puede explicar este comportamiento? ¿No deberían ser idénticas las líneas primera y tercera?
¡Gracias de antemano!
PD: 
estoy usando gcc 9.2.0en Manjaro. 
Además, cuando compilo con la -fno-builtinbandera me sale en su lugar:
-30
2
2
2
Supongo que es porque el programa no usa las funciones optimizadas de gcc, pero la pregunta sigue siendo.

printf("%i\n", strcasecmp("a", "_"));presumiblemente, esto debería tener el mismo resultado queprintf("%i\n", strcasecmp("A", "_"));Pero eso significa que una de estas dos llamadas que no distinguen entre mayúsculas y minúsculas no estará de acuerdo con su contraparte sensible a mayúsculas y minúsculas.strcasecmpque te refieres no es precisa. Más detalles en las respuestas votadas.A < _ && a > _ && A == acausaría tantos problemas.unsigned char. C17 / 18 "Manejo de cadenas <string.h>" -> "Para todas las funciones en esta subcláusula, cada carácter se interpretará como si tuviera el tipounsigned char". Esto hace la diferencia una vez que loscharvalores están fuera del rango ASCII 0-127.Respuestas:
El comportamiento es correcto.
Por la
str\[n\]casecmp()especificación POSIX :Eso también es parte de la sección NOTAS de la página de manual de Linux :
¿Por qué?
Como @HansOlsson señaló en su respuesta , hacer comparaciones que no distingan entre mayúsculas y minúsculas entre letras y permitir que todas las demás comparaciones tengan sus resultados "naturales" tal como se hace
strcmp(), interrumpiría la clasificación.Si
'A' == 'a'(la definición de una comparación entre mayúsculas y minúsculas), entonces'_' > 'A'y'_' < 'a'(los resultados "naturales" en el conjunto de caracteres ASCII) no pueden ser ambos verdaderos.fuente
'_' > 'A' && '_' < 'a'; No parece ser el mejor ejemplo.'a' == 'A', por definición , si lo hace una comparación entre los valores "naturales" de'a','A'y'_', que no se puede hacer una comparación entre mayúsculas y minúsculas entre'A'y'a'para conseguir la igualdad y obtener ordenar resultados consistentes.'a','A'y'_', pasando por los 6 órdenes de inserción en el árbol, y comparando los resultados de las "letras minúsculas" como se especifica con las "letras convertidas únicas" de la pregunta cuando se trata de una comparación letra a letra ". Por ejemplo, usar el último algoritmo y comenzar con'_','a'y'A'terminar en lados opuestos del árbol, pero se definen como iguales. El algoritmo "solo convertir letras a minúsculas en las comparaciones letra-letra" está roto y esos 3 caracteres lo demuestran.'_' > 'A'y'_' < 'a'no puede ser verdad" sin decirnos por qué deberíamos haber pensado que sería. (Esa es una tarea para el que responde, no para uno de los millones de lectores.)Otros enlaces, http://man7.org/linux/man-pages/man3/strcasecmp.3p.html para strcasecmp dicen que la conversión a minúsculas es el comportamiento correcto (al menos en la ubicación POSIX).
La razón de ese comportamiento es que si usa strcasecmp para ordenar una serie de cadenas, es necesario obtener resultados razonables.
De lo contrario, si intenta ordenar "A", "C", "_", "b" utilizando, por ejemplo, qsort, el resultado dependerá del orden de las comparaciones.
fuente
Eso es correcto, ¡y es lo
strcasecmp()que debería hacer la función ! Es unaPOSIXfunción, más que parte delCEstándar, pero, de " The Open Group Base Especificaciones, Issue 6 ":Por cierto, este comportamiento también es pertinente para la
_stricmp()función (como se usa en Visual Studio / MSCV):fuente
El código decimal ASCII para
Aes65para_es95y paraaes97, porstrcmp()lo que está haciendo lo que se supone que debe hacer. Lexicográficamente hablando_es más pequeño entoncesay más grande queA.strcasecmp()se consideraráAcomoa*, y dado queaes más grande que_la salida, también es correcta.* El estándar POSIX.1-2008 dice de estas funciones (strcasecmp () y strncasecmp ()):
Fuente: http://man7.org/linux/man-pages/man3/strcasecmp.3.html
fuente
Aes "más grande" que_cuando se compara entre mayúsculas y minúsculas, y se pregunta por qué el resultado no es el mismo que cuando se compara entre mayúsculas y minúsculas.Sincestrcasecmp () `no distingue entre mayúsculas y minúsculas, considerará que A como a` es una deducción no válida. Una rutina que no distingue entre mayúsculas y minúsculas podría tratar todas las letras mayúsculas como si fueran letras minúsculas, podría tratar todas las letras minúsculas como si fueran letras mayúsculas o podría tratar cada letra mayúscula como igual a su letra minúscula correspondiente y viceversa, pero aún así compararlas a caracteres que no son letras con sus valores sin formato. Esta respuesta no indica una razón para preferir ninguna de esas posibilidades (la razón correcta es que la documentación dice que use minúsculas).