Devuelve sin un comando de "retorno"


8

Lenguaje de programación C, compilado con gcc, terminal bash en WSL

He escrito una función recursiva, para encontrar el número más bajo en una matriz, que funciona bien.

/*01*/    int minimo(int array[], int n)
/*02*/    {
/*03*/      static int min = 0;
/*04*/    
/*05*/      if (n == N)
/*06*/      {
/*07*/          return array[n-1];
/*08*/      }
/*09*/      else
/*10*/      {
/*11*/          min = minimo(array, n+1);
/*12*/          if(array[n]<min){
/*13*/              min = array[n];
/*14*/          }
/*15*/      }
/*16*/    }

El único problema es que no debería funcionar, porque no devuelve "min" a la persona que llama ...

int main()
{
    //Var
    int array[N] = {10, 2, 5, 1, 7};
    printf("Min: %d\n", minimo(array, 0));
}

Mi preocupación es en realidad un problema, pero no en mi máquina en la que la función funciona tan bien como está; es un problema en las computadoras portátiles e IDE de mis amigos, intenté copiar a XCode en la Macbook de un amigo y no funcionaría si la línea "return min"; no se agregó al final de la función.

Entre la línea 15-16 tengo que agregar return min;

/*15*/      }
            return min;
/*16*/    }

Mis preguntas para usted son las siguientes:

  1. ¿Cómo puede una función devolver una variable automáticamente ?
  2. ¿Es posible que devuelva la única variable que creé (static int min)?
  3. ¿O es un "problema" relacionado con el atributo estático que tiene la variable?
  4. ¿Tiene algo que ver con la naturaleza de la función ( recursiva )?

Esta es mi primera publicación, por favor sea amable si no cumplo con alguna regla del foro.


Lea la pregunta SO: stackoverflow.com/q/204476/8339821 y las respuestas. Esto lo llevará al punto que le maindevuelve su función.
Yvw

A primera vista, parece algo específico de WSL, no específico de gcc. Parece que WSL automáticamente "piensa" por usted y corrige el código por sí mismo.
RobertS apoya a Monica Cellio

@ ЯрославМашко Esto es algo completamente diferente y no tiene nada que ver con esta pregunta. El problema no se trata del valor de retorno, mainsino del valor de retorno "automático" de una función en una implementación específica.
RobertS apoya a Monica Cellio

@RobertSsupportsMonicaCellio Sí, tienes razón. Leí la pregunta nuevamente y me di cuenta de que el SO quiere saber qué regresa realmente su función . Pensé que de alguna manera extraña el regreso de main. Luego, esta respuesta brinda información completa sobre el tema: stackoverflow.com/a/1610454/8339821 . El punto principal es que algún Cestándar particular devuelve cero en ausencia de una declaración de devolución.
Yvw

Debe compilar su archivo con un -Wallinterruptor y ver qué le dice el compilador.
Yvw

Respuestas:


5

Mi preocupación es en realidad un problema, pero no en mi máquina en la que la función funciona tan bien como está; es un problema en las computadoras portátiles e IDE de mis amigos, intenté copiar a XCode en la Macbook de un amigo y no funcionaría si la línea "return min"; no se agregó al final de la función.

Ejemplo típico de comportamiento indefinido . Funciona en una máquina pero no en otra. Funciona de día pero no de noche. Funciona con un compilador pero no con otro. Cuando invoca un comportamiento indefinido, el estándar C no impone requisitos sobre cómo debe comportarse el código.

C11 estándar 6.9.1.12

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

En su código, eso es precisamente lo que sucede. Invoca un comportamiento indefinido cuando intenta imprimir el valor de retorno.

Al contrario de lo que muchos creen, está completamente permitido omitir la declaración de devolución en una función no nula. Solo se convierte en un comportamiento indefinido si intenta utilizar el valor de retorno inexistente.

Para evitar esto, compile siempre con al menos -Wall -Wextra.


¡Y no lo olvides -Werror!
Jonathon Reinhart

@JonathonReinhart Bueno, ese es el tipo de discusión que requiere cerveza. :)
klutt

1
@JonathonReinhart Lo importante es cuidar las advertencias. Si al codificador no le importa y está usando -WerrorSO, recibe una pregunta con "¿Por qué esto no se compila?" y sin ella "¿Por qué esto se comporta extraño?" Si bien estoy de acuerdo en que ese parámetro es algo bueno, se pierde el objetivo.
klutt

1
Mi opinión es que -Werrorevita preguntas SO innecesarias como esta, porque el usuario se ve obligado a preocuparse por las advertencias cuando no tiene un ejecutable roto para ejecutar :-)
Jonathon Reinhart

2
Quizás GCC debería, por defecto, simplemente presentar mensajes de error en formato HTML con el tema Stack Overflow y resultados de búsqueda incrustados
Jonathon Reinhart

2

¿Cómo puede una función devolver una variable automáticamente?

Sigue el protocolo. Sabe que el retorno de la función debe encontrar el valor devuelto en alguna ubicación y un explícito returnde esa función llenará esa ubicación. Si no llama return, se conservará algún valor aleatorio en la ubicación dada.

¿Es posible que devuelva la única variable que creé (static int min)?

No, no está definido lo que devuelve. Puede ser lo que sea.

¿O es un "problema" relacionado con el atributo estático que tiene la variable?

Nuevamente, lo que devuelve no está definido.

¿Tiene algo que ver con la naturaleza de la función (recursiva)?

Si y no. Si la función se define como externa, el valor devuelto sigue otro protocolo como en el caso de las funciones estáticas.

Puede suceder cualquier cosa en el código final, el lenguaje C no impone la forma de implementar una función, ya sea recursiva o no. Por ejemplo, en caso de que la función sea recursiva y pueda calcularse previamente, solo el valor final puede reemplazarse en el lugar de la llamada. Esto también es correcto ya que el resultado final del programa es el resultado esperado, conforme a la semántica operativa que define C enISO9899 .

Cito del documento oficial:

4 En la máquina abstracta, todas las expresiones se evalúan según lo especificado por la semántica. Una implementación real no necesita evaluar parte de una expresión si puede deducir que su valor no se usa y que no se producen los efectos secundarios necesarios (incluidos los causados ​​por llamar a una función o acceder a un objeto volátil).

También puede reemplazar una llamada con el valor de esa llamada y esto es correcto.

Entonces, en todas sus preguntas, la respuesta es un comportamiento indefinido .


1

¿Cómo puede una función devolver una variable automáticamente?

Sucede por casualidad, la minvariable está en el registro de retorno correcto para el ABI.

¿Es posible que devuelva la única variable que creé (static int min)?

Creo que está más relacionado con que se haya utilizado justo antes de la salida de la función, pero supongo que aquí: este no es un comportamiento definido en lenguaje C, y funcionó por casualidad.

¿O es un "problema" relacionado con el atributo estático que tiene la variable?

¿Tiene algo que ver con la naturaleza de la función (recursiva)?

Como se trataba de un comportamiento casual, podría serlo o no. La diferencia entre aleatorio y determinista es que tiene tantas variables que deja de explicar.


-3

Supongo que definiste N en alguna parte (probablemente N = 5 en tu caso).

La mayoría de los compiladores agrega automáticamente la declaración "return 0" si falta la declaración return.

* Ver comentarios para más información. En realidad es un comportamiento indefinido *

En su función recursiva, es mejor pasar la longitud restante de la matriz y detenerse cuando alcanza n == 0.

Evite mirar variables globales o define funciones internas.

int minimo(int array[], int n)
{
  ...
  if (n == 0)
  ...
            min = minimo(array, n-1);
  ...
}

(se requiere otra modificación)

En realidad, debe conocer la longitud de la matriz solo en la función principal, así que llámela como:

printf("Min: %d\n", minimo(array, N));

55
¡No! Excepto main()en las implementaciones de C99 (o posterior) (donde return 0;se agrega a en ausencia de una declaración de retorno anterior) , la falla returnes UB .
pmg

@pmg en algún lugar del SO, he leído que la redacción se reduce a C89. Y eso es un mínimo que puedo obtener hoy.
Yvw

@ ЯрославМашко: C89 no menciona el valor de retorno predeterminado; C99 (y de manera similar en C11 ): "... llegando al} que termina la función principal devuelve un valor de 0". (el énfasis es mío)
pmg
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.