Segment default, compilando un ejemplillo en c

Buenas, pos me ha surgido una duda cuando estaba haciendo unos ejemplillos con punteros en C. Aqui os pongo el codigo:
#include <stdio.h>
#include <stdlib.h>

struct rectangulo {
   int ancho;
   int largo;
} ;

int main(int argc, char *argv[])
{
   struct rectangulo *pp;
   pp = (struct rectangulo *) malloc (sizeof (struct rectangulo));
   
   printf ("Introduce valor del ancho del rectangulo: ");
   scanf ("%d", (pp->ancho));
   printf ("\nIntroduce ahora el largo: ");
   scanf ("%d", (pp->largo));

   printf ("\nEl area del rectangulo es: %d", (pp->ancho) * (pp->largo));
   return 0;
}


EL compilador me suelta 2 Warnings, que no se como podria hacer para eliminarlos, son los siguientes:
$ gcc estructuras.c  -o estructuras -Wall -g
estructuras.c: In function 'main':
estructuras.c:14: warning: format '%d' expects type 'int *', but argument 2 has type 'int'
estructuras.c:16: warning: format '%d' expects type 'int *', but argument 2 has type 'int'


El segment default me lo suelta nada mas introducir el primer valor, por lo que el error tendria que estar en el scanf, supongo que es por los Warnings, tb he visto googleando que podria ser por el puntero que podria querer pisar memoria y el kernel no se lo permitiria por lo que le he puesto un malloc() pero me sigue dando el mismo error.

El depurador me suelta esto:
Failed to read a valid object file image from memory.
Introduce valor del ancho del rectangulo: 2

Program received signal SIGSEGV, Segmentation fault.
0xb7e958f7 in _IO_vfscanf () from /lib/libc.so.6


Haber si me podeis echar una manita :)

Gracias y Salu2!!
Es simple, scanf espera que el primer parámetro de ESA llamada sea de tipo int* y tu le estás pasando un int. Así que SEGFAULT !

Poco a poco:

    struct rectangulo *pp;
   pp = (struct rectangulo *) malloc (sizeof (struct rectangulo));


Te sobra el casting, los punteros pueden ir de T* -> void* -> T* sin castings.

    printf ("Introduce valor del ancho del rectangulo: ");
   scanf ("%d", (pp->ancho));
   printf ("\nIntroduce ahora el largo: ");
   scanf ("%d", (pp->largo));


Como bien te dice el warning, ahí no quieres pp->algo quieres un puntero a algo, es decir LA DIRECCIÓN de algo: &pp->algo.

Y quita esos paréntesis, hacen más dificil de leer el código y simplemente demuestran que no leiste las normas de precedencia de los operadores :P Básicamente -> liga muy fuerte, en este caso, mucho más que ,, así que los paréntesis sobran.

    printf ("\nEl area del rectangulo es: %d", (pp->ancho) * (pp->largo));


Una vez más, quita los paréntesis, -> liga mucho más fuerte que *.

    return 0;


Eso debería ser return EXIT_SUCCESS;

- ferdy

-----------------------------

Se me olvidaba explicar el segfault. Básicamente scanf lo que hace es recibir un puntero donde guardar el dato que lee. Tu le estás pasando pp->algo, ese valor es un entero que tiene un valor desconocido y aleatorio.

El segfault puede ser por dos razones:

1) Si sizeof(int) == sizeof(int*) entonces scanf tomará ese valor desconocido y aleatorio como un puntero e intentará grabar en una zona a la que SEGURO que no tienes acceso el valor leido, de ahí el segmentation fault.

2) Si sizeof(int) != sizeof(int*) entonces la extensión de signo producirá una dirección errónea y de ahí el segmentation fault.

- ferdy
Gracias por las aclaraciones, todo por los &, mira que lo probé, pero creo recordar que lo hice sin el malloc(), y entonces me saltada de todos modos el segment default.

No tengo muy claro el concepto de casting, si me lo puedes aclarar te lo agradeceria

Gracias y Salu2!!!

PD: Echare una buena ojeada a la tabla de precedencia ;)
Gracias por las aclaraciones, todo por los &, mira que lo probé, pero creo recordar que lo hice sin el malloc(), y entonces me saltada de todos modos el segment default.


PERSONALMENTE creo que esta es la forma incorrecta de aprender C. Por lo general es mejor saber QUÉ se está haciendo en lugar de probar a cambiar &, *, y malloc's aquí y alli. Obviamente no deja de ser una opinión personal.

Un casting simplemente es una herramienta para saltarse el sistema de tipos de C. Si sabes lo que haces puede ser poderosa, si no sabes lo que haces no deberías usarla. Básicamente te permite hacer que el compilador CREA que cierta expresión es de un tipo que en principio NO es.

procedencia


precEdencia. Proceder proceden todos del mismo sitio, de nuestros creadores y profetas K&R (hint hint).
Ferdy escribió:procedencia


precEdencia. Proceder proceden todos del mismo sitio, de nuestros creadores y profetas K&R (hint hint).

XD

Gracias de nuevo y Salu2!!!
4 respuestas