Funciones recursivas en C: ¿el retorno es siempre necesario?

Esta es la primera vez que juego con funciones recursivas, y esta función que escribí devuelve el tamaño de una cadena si solo contiene letras en orden ascendente, y si no, devuelve -1.

No entiendo por qué funciona con ambos códigos, después de que saqué la segunda “devolución”. ¿Es uno más derrochador que el otro? Apreciaría alguna idea.

con ” return only_ascending_letters (cadena, índice + 1);”

#include  int only_ascending_letters(char string[], int index); void main() { char string1[]="Hi my name is pete"; char string2[]="aabcdefg"; printf("the first string is %d and the second one is %d\n",only_ascending_letters(string1,0),only_ascending_letters(string2,0)); } int only_ascending_letters(char string[], int index){ if(!string[index]) return index; if(((string[index]>='a'&&string[index]='A'&&string[index]<='Z'))&&((string[index]<=string[index+1])||!string[index+1])) return only_ascending_letters(string, index+1); else return -1; } 

con “only_ascending_letters (cadena, índice + 1);”

  #include  int only_ascending_letters(char string[], int index); void main() { char string1[]="Hi my name is pete"; char string2[]="aabcdefg"; printf("the first string is %d and the second one is %d\n",only_ascending_letters(string1,0),only_ascending_letters(string2,0)); } int only_ascending_letters(char string[], int index){ if(!string[index]) return index; if(((string[index]>='a'&&string[index]='A'&&string[index]<='Z'))&&((string[index]<=string[index+1])||!string[index+1])) /*Took out the return*/ only_ascending_letters(string, index+1); else return -1; } 

Sí, absolutamente necesitas la devolución. Tenga en cuenta que las reglas del lenguaje C son un poco laxas con respecto a este problema, y ​​si no hubiera utilizado el valor de retorno, estaría bien sin él. Sin embargo, utiliza el valor de retorno, por lo que necesita la statement de retorno.

Lo que ve es probablemente causado por el detalle de implementación que funciona en algunas architectures devueltas (valores integrales) al establecer un registro conocido en ese valor (eax en i386). Por lo tanto, si la llamada recursiva más baja return y establece este registro, y las llamadas intermedias no pisan ese registro, verá que funciona. Sin embargo, no debes confiar en eso.

Tenga en cuenta que los buenos comstackdores reconocerán que esto es una llamada recursiva de cola y comstackrán ambas variantes básicamente de la misma manera.

En primer lugar, main() devuelve un int (en realidad, un tipo compatible con int).

Segundo, debes formatear tu código más. El espacio en blanco es tu amigo, al igual que los saltos de línea. Era difícil saber si el código sin retorno era realmente correcto porque la mayoría se ejecutaba fuera de la pantalla.

Tercero, siempre debe trabajar con todas las advertencias [razonables] habilitadas. Si lo hubiera hecho, habría atrapado la condición de retorno faltante, así como el void main() .

En cuanto a la respuesta, @jpalecek ha hecho un gran trabajo al proporcionarla. Solo me gustaría añadir que el comportamiento indefinido es una bestia. Si confías en él, un progtwig “operativo” puede dejar de hacerlo solo porque decidiste comstackrlo nuevamente, escuchar música mientras lo ejecutabas o cambiar la fase de la luna.

Todo lo que pude encontrar en la norma [99] fue la cláusula 12.9.1 :

Si se alcanza el} que termina una función, y el llamante utiliza el valor de la llamada a la función, el comportamiento no está definido.

Tienes dos condiciones de salida. O se sale del final de la cadena, en cuyo caso se cumple su condición de caracteres ascendentes y devuelve la longitud de la cadena, o encuentra un carácter que falla su prueba ascendente, en cuyo caso devuelve -1.

No devolver el valor de la llamada a la función recursiva puede funcionar en algunas implementaciones del comstackdor, pero con un comstackdor diferente o diferentes banderas de optimización, puede que no funcione, por lo que debe mantener el retorno en su código.