textos sirve resueltos que para ejercicios dev concatenar con comparar como caracteres cadenas cadena c++ c linux strcmp

c++ - sirve - Valor de retorno de strcmp() incoherente al pasar cadenas como punteros o como literales



strcmp c++ para que sirve (2)

Estaba jugando con strcmp cuando noté esto, aquí está el código:

#include <string.h> #include <stdio.h> int main(){ //passing strings directly printf("%d/n", strcmp("ahmad", "fatema")); //passing strings as pointers char *a= "ahmad"; char *b= "fatema"; printf("%d/n",strcmp(a,b)); return 0; }

la salida es:

-1 -5

¿No debería strcmp funcionar igual? ¿Por qué es que se me da un valor diferente cuando paso cadenas como "ahmad" o como char* a = "ahmad" . Cuando pasa valores a una función, se asignan en su pila ¿verdad?


Creo que crees que el valor devuelto por strcmp debe depender de alguna manera de las cadenas de entrada que se le pasen de una manera que no está definida por la especificación de la función. Esto no es correcto Ver por ejemplo la definición POSIX:

http://pubs.opengroup.org/onlinepubs/009695399/functions/strcmp.html

Al finalizar, strcmp () devolverá un entero mayor que, igual o menor que 0, si la cadena apuntada por s1 es mayor, igual o menor que la cadena apuntada por s2, respectivamente.

Esto es exactamente lo que estás viendo. La implementación no necesita hacer ninguna garantía sobre el valor de retorno exacto , solo que es menor que cero, igual a cero o mayor que cero, según corresponda.


Lo más probable es que vea el resultado de una optimización del compilador. Si probamos el código usando gcc en godbolt , con el nivel de optimización -O0 , podemos ver que en el primer caso no llama a strcmp :

movl $-1, %esi #, movl $.LC0, %edi #, movl $0, %eax #, call printf #

Como está usando constantes como argumentos para strcmp el compilador puede realizar plegamientos constantes y llamar a un compilador intrínseco en tiempo de compilación y generar -1 , en lugar de tener que llamar a strcmp en tiempo de ejecución, que se implementa en la biblioteca estándar y tendrá una implementación diferente luego una estructura de tiempo de compilación probablemente más simple.

En el segundo caso genera una llamada a strcmp :

call strcmp # movl %eax, %esi # D.2047, movl $.LC0, %edi #, movl $0, %eax #, call printf #

Esto es coherente con el hecho de que gcc tiene un built-in para strcmp , que es lo que usará gcc durante el plegado constante.

Si realizamos una prueba adicional utilizando el nivel de optimización de -O1 o una mayor gcc podremos doblar ambas cajas y el resultado será -1 para ambos casos:

movl $-1, %esi #, movl $.LC0, %edi #, xorl %eax, %eax # call printf # movl $-1, %esi #, movl $.LC0, %edi #, xorl %eax, %eax # call printf #

Con más opciones de optimización activadas, el optimizador puede determinar que b apuntan a las constantes conocidas también en tiempo de compilación y también puede calcular el resultado de strcmp para este caso también durante el tiempo de compilación.

Podemos confirmar que gcc está utilizando la función incorporada construyendo con la bandera -fno-builtin y observando que se generará una llamada a strcmp para todos los casos.

clang es ligeramente diferente en el sentido de que no se dobla en absoluto con -O0 sino que se pliega a -O1 y más arriba para ambos.

Tenga en cuenta que cualquier resultado negativo es totalmente conforme, podemos ver yendo al borrador de la sección estándar C99 7.21.4.2 La función strcmp que dice ( énfasis mío ):

int strcmp(const char *s1, const char *s2);

La función strcmp devuelve un número entero mayor, igual o menor que cero , en consecuencia, como la cadena apuntada por s1 es mayor, igual o menor que la cadena apuntada por s2.

technosurus señala que strcmp se especifica para tratar las cadenas como si estuvieran compuestas de caracteres sin signo , esto está cubierto en C99 en 7.21.1 que dice:

Para todas las funciones en esta subcláusula, cada carácter se interpretará como si tuviera el tipo carácter no firmado (y, por lo tanto, cada representación de objeto posible es válida y tiene un valor diferente).