/
Inicio :: Foros

 F.A.Q.F.A.Q.                  Conéctese para revisar sus mensajesConéctese para revisar sus mensajes   

Warning en una funcion

 
      Índice del Foro elrincondelc.com -> Principiantes C/C++
Ver tema anterior :: Ver siguiente tema  
AutorMensaje
cigoba



Registrado: 27 Ago 2007
Mensajes: 43

MensajePublicado: 17/10/2007 4:08 pm
Título: Warning en una funcion

Hola gente, nuevamente ando por estos foros con un problema.

Cuando compilo el codigo C que coloco al final (uso Dev-C++) me aparece el siguiente warning que dice:
"Linea 58 [Warning] control reaches end of non-void function"
y no se como eliminar ese error, intente de todo pero no logre solucionar el problema.

Otra duda que tengo es que a la variable declarada como:
Código:

char *unid[10]={"cero", "uno", "dos", "tres", "cuatro", "cinco", "seis", "siete", "ocho", "nueve"};

la quiero hacer de tipo const char puesto que esta nunca va a variar y hago:
Código:
const char *unid[10]={"cero", "uno", "dos", "tres", "cuatro", "cinco", "seis", "siete", "ocho", "nueve"};

pero cuando lo compilo asi, me aparecen warnings en las lineas: 28, 31, 34, 37, 40, 43, 46, 49, 52, 55, que dice "Linea # [Warning] return discards qualifiers from pointer target type"; y por supuesto sigue apareciendo el warning que describi anteriormente en la ultima linea 58.

Tal vez uds. puedan decirme que es lo que estoy haciendo mal y darme la solucion. Desde ya muchas gracias.

Este es el codigo:

Código:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *num_a_letras(char *num1);

int main(void)
{
    char numero[8];
    printf("Entero de 0 a 9: ");
    gets(numero);
    printf("Numero: %s\n", num_a_letras(numero));
    system("PAUSE");
    return EXIT_SUCCESS;
}

char *num_a_letras(char *num1)
{
    int tam, n_num1;
    char *unid[10]={"cero", "uno", "dos", "tres", "cuatro", "cinco", "seis", "siete", "ocho", "nueve"};
    tam=strlen(num1);
   n_num1=atoi(num1);
    if(tam==1)
   {
        switch(n_num1)
        {
            case 0:
                return unid[0]; /* Linea 28 */
                break;
            case 1:
                return unid[1];  /* Linea 31 */
                break;
            case 2:
                return unid[2];  /* Linea 34 */
                break;
            case 3:
                return unid[3];  /* Linea 37 */
                break;
            case 4:
                return unid[4];  /* Linea 40 */
                break;
            case 5:
                return unid[5];  /* Linea 43 */
                break;
            case 6:
                return unid[6];  /* Linea 46 */
                break;
            case 7:
                return unid[7];  /* Linea 49 */
                break;
            case 8:
                return unid[8];  /* Linea 52 */
                break;
            case 9:
                return unid[9];  /* Linea 55 */     
        }
    }
} /* Linea 58 */

_________________
esta es mi firma.
Volver arriba
cheroky



Registrado: 22 Sep 2005
Mensajes: 1372
Ubicación: En ecx esperando un call

MensajePublicado: 17/10/2007 8:08 pm
Título:

cigoba escribió:
Cuando compilo el codigo C que coloco al final (uso Dev-C++) me aparece el siguiente warning que dice:
"Linea 58 [Warning] control reaches end of non-void function"
y no se como eliminar ese error, intente de todo pero no logre solucionar el problema.

Esto es debido al supuesto caso de que el bloque switch no se cumpliera no hay dirección de retorno explicita, en otras palabras un return con el tipo de dato apropiado, en este caso lo idóneo bien podría ser NULL

cigoba escribió:
pero cuando lo compilo asi, me aparecen warnings en las lineas: 28, 31, 34, 37, 40, 43, 46, 49, 52, 55, que dice "Linea # [Warning] return discards qualifiers from pointer target type"; y por supuesto sigue apareciendo el warning que describi anteriormente en la ultima linea 58.

El waning es debido a que no coinciden el calificador const de los punteros que retornas con el tipo de retorno de la función, el prototipo de esta debería ser (añadiendo el calificador const al parametro y al retorno):
Código:
const char* num_a_letras(const char *num1);


También podrías usar la macro isdigit para validar la entrada.


S2.
_________________
- Explícito es mejor que implícito.
- Simple es mejor que complejo.
- Complejo es mejor que complicado.
- Plano es mejor que anidado.
- Ralo es mejor que denso.
Volver arriba
cigoba



Registrado: 27 Ago 2007
Mensajes: 43

MensajePublicado: 17/10/2007 8:26 pm
Título:

Gracias cheroky. Siguiendo tus consejos el código me queda de la siguiente manera, y compila perfectamente y ya no me tira ningún warining. Ahora no entiendo muy bien porqué debo colocarle return NULL; al final de la función si esta retorn si o si un valor. Te agradecería muchisimo si me explica un poquito más este tema.
Ya me agarro sueño, por ahora me voy a dormir.
Código:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const char *num_a_letras(char *num1);

int main(void)
{
    char numero[8];
    printf("Entero de 0 a 9: ");
    gets(numero);
    printf("Numero: %s\n", num_a_letras(numero));
    system("PAUSE");
    return EXIT_SUCCESS;
}

const char *num_a_letras(char *num1)
{
    int tam, n_num1;
    const char *unid[10]={"cero", "uno", "dos", "tres", "cuatro", "cinco", "seis", "siete", "ocho", "nueve"};
    tam=strlen(num1);
   n_num1=atoi(num1);
    if(tam==1)
   {
        switch(n_num1)
        {
            case 0:
                return unid[0];
                break;
            case 1:
                return unid[1]; 
                break;
            case 2:
                return unid[2];
                break;
            case 3:
                return unid[3]; 
                break;
            case 4:
                return unid[4];
                break;
            case 5:
                return unid[5];
                break;
            case 6:
                return unid[6];
                break;
            case 7:
                return unid[7]; 
                break;
            case 8:
                return unid[8];
                break;
            case 9:
                return unid[9];
        }
    }
    return NULL;
}


saludos
_________________
esta es mi firma.
Volver arriba
cheroky



Registrado: 22 Sep 2005
Mensajes: 1372
Ubicación: En ecx esperando un call

MensajePublicado: 17/10/2007 8:53 pm
Título:

cigoba escribió:
Ahora no entiendo muy bien porqué debo colocarle return NULL; al final de la función si esta retorn si o si un valor. Te agradecería muchisimo si me explica un poquito más este tema.
Ya me agarro sueño, por ahora me voy a dormir.


Con NULL retornas una dirección de memoria invalida valida, aunque parezca enrevesado es simple, en el supuesto caso de que no tengas que retornar la dirección correspondiente a un objeto, retornas la macro NULL como "dirección" indicando que la función no ha procesado ningún dato valido, pudiéndose usar para, por ejemplo, evaluar el retorno en un if, for, etc.

S2.
_________________
- Explícito es mejor que implícito.
- Simple es mejor que complejo.
- Complejo es mejor que complicado.
- Plano es mejor que anidado.
- Ralo es mejor que denso.
Volver arriba
cigoba



Registrado: 27 Ago 2007
Mensajes: 43

MensajePublicado: 18/10/2007 4:28 am
Título:

Gracias, claro como el agua.
_________________
esta es mi firma.
Volver arriba
rir3760



Registrado: 01 Oct 2004
Mensajes: 3841
Ubicación: Mexico

MensajePublicado: 18/10/2007 7:54 am
Título:

El mensaje de advertencia:
Cita:
Linea 58 [Warning] control reaches end of non-void function

Se debe (como ya se indico) a una posible salida de esa funcion sin haber asignado un valor de retorno. Esto tecnicamente no es un error pero si una mala practica ya que en un caso asi el valor de retorno de la funcion es "no definido".

Y si revisas el bloque switch en la funcion "num_a_letras" te daras cuenta de que hay una relacion entre el digito introducido y el indice de la cadena literal que se debe devolver. Esa funcion se puede reducir a:
Código:
char *num_a_letras(char *numero)
{
   char *unidad[] = {
      "cero", "uno", "dos",
      "tres", "cuatro", "cinco",
      "seis", "siete", "ocho",
      "nueve"
   };
   
   if (strlen(numero) != 1 || !isdigit(numero[0]))
      return NULL; /* manejo de error */
   
   return unidad[numero[0] - '0'];
}


El otro mensaje:
Cita:
Linea # [Warning] return discards qualifiers from pointer target type

Se debe a que no hay problema al agregar calificadores como "const" a un tipo, en otras palabras donde sea que se requiera un objeto de tipo "char const *" se puede utilizar uno de tipo "char *".

El problema es que lo opuesto no aplica: no se pueden descartar calificadores como const. Siguiendo el ejemplo de tu programa el error es:
Código:
char *num_a_letras(char *numero)
{
   char const *unidad[] = {
      "cero", "uno", "dos",
      "tres", "cuatro", "cinco",
      "seis", "siete", "ocho",
      "nueve"
   };
   
   /* ... */
   
   return unidad[numero[0] - '0'];
}

Ya que estarias descartando el calificador const del array "unidad". Si uno quisiera "arreglarlo" de la forma mas rapida (poniendo la escopeta y jalando el gatillo) se puede convertir el "char const *" a "char *" mediante una conversion explicita:
Código:
return (char *) unidad[numero[0] - '0'];

Pero aun asi el objeto seguiria bajo los efectos de los calificadores descartados. Si se trata de modificar el objeto apuntado por ese puntero se produciria un error ya que aun cuando el puntero no lo indique (mediante su nuevo tipo "char *") el objeto apuntado seguiria siendo de solo lectura (debido al calificador descartado const).

Un saludo
_________________
The capacity to learn is a gift;
The ability to learn is a skill;
The willingness to learn is a choice.
--
Rebec of Ginaz
Volver arriba
cigoba



Registrado: 27 Ago 2007
Mensajes: 43

MensajePublicado: 18/10/2007 11:24 am
Título:

gracias rir3706, muy buena tu apreciación

Saludos a ambos
_________________
esta es mi firma.
Volver arriba
cheroky



Registrado: 22 Sep 2005
Mensajes: 1372
Ubicación: En ecx esperando un call

MensajePublicado: 18/10/2007 7:01 pm
Título:

Cuando en una expresión del tipo puntero a cadena literal se trata es recomendable usar el calificador const. Por definición un literal de cadena se aloja en una zona de memoria de solo lectura, si intentáramos sobrescribir esta zona el programa reventaría, con dicho calificador, en fase de diseño, obtendremos un error bastante menos doloroso.

Por tanto la propuesta del prototipo de la función:
Código:
const char* num_a_letras(const char *num1);

El parámetro se sugiere también const puesto que no se modifica el objeto apuntado.

En el aviso:
Cita:
Linea # [Warning] return discards qualifiers from pointer target type

El tipo de retorno de la función descarta el calificador del puntero, siendo este puntero marcado como const. Este warning se elimina calificando el retorno como const, por las razones que comentaba anteriormente y añadiendo que una función que retorna un objeto se puede usar como l-value de dicho objeto.

Otra propuesta de tu ejercicio basado en el pading de un literal de cadena.
Código:

const char *num_a_letras2(const char *num)
{
return (*num - '0') * 7 + "cero\0\0\0uno\0\0\0\0dos\0\0\0\0tres\0\0\0cuatro\0"
                            "cinco\0\0seis\0\0\0siete\0\0ocho\0\0\0nueve\0\0";
}


S2.
_________________
- Explícito es mejor que implícito.
- Simple es mejor que complejo.
- Complejo es mejor que complicado.
- Plano es mejor que anidado.
- Ralo es mejor que denso.
Volver arriba
rir3760



Registrado: 01 Oct 2004
Mensajes: 3841
Ubicación: Mexico

MensajePublicado: 19/10/2007 8:00 am
Título:

Una ultima nota: si el valor de retorno de una funcion es un puntero el objeto apuntado debe ser uno con el tipo (tecnicamente clase) de almacenamiento estatico ya sea implicitamente (como en el caso de las cadenas literales) o explicitamente mediante el uso de la palabra reservada "static".

Por ejemplo si modificamos la funcion a:
Código:
char *num_a_letras(char *numero)
{
   char unidad[][32] = {
      "cero", "uno", "dos",
      "tres", "cuatro", "cinco",
      "seis", "siete", "ocho",
      "nueve"
   };
   
   if (strlen(numero) != 1 || !isdigit(numero[0]))
      return NULL; /* manejo de error */
   
   return unidad[numero[0] - '0'];
}

Su valor de retorno no seria valido ya que el array "unidad" desapareceria al terminar la funcion.

Para que este ejemplo sea correcto debemos declarar el array con el tipo de almacenamiento estatico:
Código:
static char unidad[][32] = { ... };


Un saludo
_________________
The capacity to learn is a gift;
The ability to learn is a skill;
The willingness to learn is a choice.
--
Rebec of Ginaz
Volver arriba
cheroky



Registrado: 22 Sep 2005
Mensajes: 1372
Ubicación: En ecx esperando un call

MensajePublicado: 19/10/2007 10:38 am
Título:

rir3760 escribió:
Su valor de retorno no seria valido ya que el array "unidad" desapareceria al terminar la funcion.


El array es eliminado de la pila, pero como el retorno se refiere a una dirección de un objeto con categoría de almacenamiento static no puede suscitar un problema de dangling pointer.
Aunque las especificaciones del lenguaje no suelen o no determinan comportamientos a bajo nivel en ciertos escenarios estos mecanismos si son concluyentes, antes de variar el puntero de pila se mueve la dirección almacenada al registro eax usualmente el registro (por convención) usado para el retorno de funciones. En otras arquitecturas no x86 el mecanismo es similar.

S2.
_________________
- Explícito es mejor que implícito.
- Simple es mejor que complejo.
- Complejo es mejor que complicado.
- Plano es mejor que anidado.
- Ralo es mejor que denso.
Volver arriba
rir3760



Registrado: 01 Oct 2004
Mensajes: 3841
Ubicación: Mexico

MensajePublicado: 19/10/2007 2:59 pm
Título:

cheroky escribió:
rir3760 escribió:
Su valor de retorno no seria valido ya que el array "unidad" desapareceria al terminar la funcion.

El array es eliminado de la pila, pero como el retorno se refiere a una dirección de un objeto con categoría de almacenamiento static no puede suscitar un problema de dangling pointer.

En el fragmento de codigo que publique:
Código:
char *num_a_letras(char *numero)
{
   char unidad[][32] = { ... };
   
   /* ... */
   
   return unidad[numero[0] - '0'];
}

Si seria un problema ya que el objeto "unidad" (de tipo "char [10][32]") tiene almacenamiento automatico, las cadenas literales solo se utilizan para inicializar cada uno de los elementos del array.

Un saludo
_________________
The capacity to learn is a gift;
The ability to learn is a skill;
The willingness to learn is a choice.
--
Rebec of Ginaz
Volver arriba
cheroky



Registrado: 22 Sep 2005
Mensajes: 1372
Ubicación: En ecx esperando un call

MensajePublicado: 19/10/2007 4:20 pm
Título:

En ese caso si, pero no en el ejemplo de cigoba

S2.
_________________
- Explícito es mejor que implícito.
- Simple es mejor que complejo.
- Complejo es mejor que complicado.
- Plano es mejor que anidado.
- Ralo es mejor que denso.
Volver arriba
rir3760



Registrado: 01 Oct 2004
Mensajes: 3841
Ubicación: Mexico

MensajePublicado: 19/10/2007 6:51 pm
Título:

Voy a terminar (mas) confundido ya que la afirmacion que hize ("Su valor de retorno no seria valido ...") fue solo en relacion a ese caso (el objeto automatico).

Un saludo
_________________
The capacity to learn is a gift;
The ability to learn is a skill;
The willingness to learn is a choice.
--
Rebec of Ginaz
Volver arriba
cheroky



Registrado: 22 Sep 2005
Mensajes: 1372
Ubicación: En ecx esperando un call

MensajePublicado: 20/10/2007 1:10 am
Título:

Te pido disculpas.

Entendí mal el post donde haces la puntualización y el code de ejemplo lo mire por encima pensando que era un calco del de cigoba, dicen que la prisa no es buena consejera :-P


S2.
_________________
- Explícito es mejor que implícito.
- Simple es mejor que complejo.
- Complejo es mejor que complicado.
- Plano es mejor que anidado.
- Ralo es mejor que denso.
Volver arriba
      Índice del Foro elrincondelc.com -> Principiantes C/C++
Página 1 de 1Todas las horas están en GMT - 8 Horas

 
No puede crear mensajes
No puede responder temas
No puede editar sus mensajes
No puede borrar sus mensajes
No puede votar en encuestas

(c) ElRincondelC.com

Un proyecto de UrlanHeat.com