Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: dRak0 en 18 Julio 2013, 15:46 pm



Título: Duda direcciones de memoria C
Publicado por: dRak0 en 18 Julio 2013, 15:46 pm
Hola que tal , como les va , espero que bien. Bueno voy a la pregunta .
Tengo el siguiente codigo :
Código:
#include <stdio.h>

main()
{
int i,array1[5]={0,1,2,3,4};
int* ptrArray1;
ptrArray1=array1;
    for(i=0;i<5;i++)
    printf("\nDesplazamiento del puntero por el array %d.Direccion: %p",*(ptrArray1+i),(ptrArray1+i));

}


El resultado es :

Desplazamiento del puntero por el array 0.Direccion: 0028FEF4
Desplazamiento del puntero por el array 1.Direccion: 0028FEF8
Desplazamiento del puntero por el array 2.Direccion: 0028FEFC
Desplazamiento del puntero por el array 3.Direccion: 0028FF00
Desplazamiento del puntero por el array 4.Direccion: 0028FF04


Perfecto el codigo funca bien todo , ahora , la pregunta. ¿Porque cada vez que corro este programa la direccion en memoria del primer elemento del array es la misma? (Al ser siempre la primera la misma , las otras son iguales xq son consecutivas a esta ).

Gracias.


Título: Re: Duda direcciones de memoria C
Publicado por: eferion en 18 Julio 2013, 15:53 pm
Cuando tú ejecutas un programa el sistema operativo reserva memoria y se la asigna al programa para que pueda trabajar.

La memoria, como norma general, está paginada y/o segmentada. Básicamente esto quiere decir que está dividida en fragmentos.

El sistema operativo dispone de un algoritmo que elige, entre los disponibles, qué segmento de memoria va a asignar al programa... dicho algoritmo suponemos que es LTI ( lineal e invariante en el tiempo ), es decir, que a una misma entrada, en unas mismas condiciones, generará siempre la misma salida.

Por tanto, si tu ejecutas varias veces seguidas tu programa sucederá lo siguiente:

Ejecutas el programa ( 1ª vez )
El sistema operativo reserva un fragmento de memoria y se lo asigna.
El programa te muestra los desplazamientos.
El programa finaliza y el fragmento de memoria es liberado.
Ejecutas el programa ( 2ª vez )
El sistema operativo, te asigna el mismo fragmento de memoria.
El programa te muestra los desplazamientos.
El programa finaliza y el fragmento de memoria es liberado.
...

Si quieres tener resultados diferentes prueba a poner una pausa en el programa, lo ejecutas una vez y, sin cerrarlo, lo vuelves a ejecutar. Verás como entonces sí te cambian las posiciones de memoria.


Título: Re: Duda direcciones de memoria C
Publicado por: Caster en 18 Julio 2013, 15:55 pm
Aprovecho este post para preguntar una cosa, que diferencia hay entre estas dos declaraciones:

Código
  1. int* ptrArray1;

Código
  1. int *ptrArray1;


Título: Re: Duda direcciones de memoria C
Publicado por: eferion en 18 Julio 2013, 15:59 pm
son idénticas.

En c y c++ los espacios no son tenidos en cuenta ( salvo en las cadenas de caracteres )


Título: Re: Duda direcciones de memoria C
Publicado por: Oblivi0n en 18 Julio 2013, 16:04 pm
Cuando tú ejecutas un programa el sistema operativo reserva memoria y se la asigna al programa para que pueda trabajar.

La memoria, como norma general, está paginada y/o segmentada. Básicamente esto quiere decir que está dividida en fragmentos.

El sistema operativo dispone de un algoritmo que elige, entre los disponibles, qué segmento de memoria va a asignar al programa... dicho algoritmo suponemos que es LTI ( lineal e invariante en el tiempo ), es decir, que a una misma entrada, en unas mismas condiciones, generará siempre la misma salida.

Por tanto, si tu ejecutas varias veces seguidas tu programa sucederá lo siguiente:

Ejecutas el programa ( 1ª vez )
El sistema operativo reserva un fragmento de memoria y se lo asigna.
El programa te muestra los desplazamientos.
El programa finaliza y el fragmento de memoria es liberado.
Ejecutas el programa ( 2ª vez )
El sistema operativo, te asigna el mismo fragmento de memoria.
El programa te muestra los desplazamientos.
El programa finaliza y el fragmento de memoria es liberado.
...

Si quieres tener resultados diferentes prueba a poner una pausa en el programa, lo ejecutas una vez y, sin cerrarlo, lo vuelves a ejecutar. Verás como entonces sí te cambian las posiciones de memoria.

No es exactamente así. El programa siempre muestra las mismas direcciones de memoria porque las direcciones que estas mostrando son direcciones virtuales (asignadas en tiempo de compilación). Si tu ejecutas 2 veces el programa, no se te asignara 2 veces el mismo bloque (si es muy seguido si, cumpliendo el principio de localidad).

Las direcciones virtuales son traducidas luego por la MMU a direcciones físicas.

Aprovecho este post para preguntar una cosa, que diferencia hay entre estas dos declaraciones:

Código
  1. int* ptrArray1;

Código
  1. int *ptrArray1;

Fijate:

Si hacemos int* ptr1,ptr2,ptr3;  entonces ptr1,ptr2 y ptr3 son punteros a un entero.
Si hacemos int *ptr1,ptr2,ptr3;  entonces solo ptr1 es un punterom. El resto son variables enteras.


Título: Re: Duda direcciones de memoria C
Publicado por: Caster en 18 Julio 2013, 16:07 pm
Gracias a los dos por responder.

Saludos


Título: Re: Duda direcciones de memoria C
Publicado por: eferion en 18 Julio 2013, 16:14 pm
Si hacemos int* ptr1,ptr2,ptr3;  entonces ptr1,ptr2 y ptr3 son punteros a un entero.
Si hacemos int *ptr1,ptr2,ptr3;  entonces solo ptr1 es un punterom. El resto son variables enteras.

Ese es un ejemplo claro de cosas que no hay que hacer a la hora de programar :)

Que luego baila algún espacio y podemos sudar tinta hasta dar con el fallo.


Título: Re: Duda direcciones de memoria C
Publicado por: 0xDani en 18 Julio 2013, 16:15 pm
Si hacemos int* ptr1,ptr2,ptr3;  entonces ptr1,ptr2 y ptr3 son punteros a un entero.
Si hacemos int *ptr1,ptr2,ptr3;  entonces solo ptr1 es un punterom. El resto son variables enteras.

Seriously? Puedes darme una referencia fidedigna en la que se indique esto?


Título: Re: Duda direcciones de memoria C
Publicado por: Caster en 18 Julio 2013, 16:17 pm
Seriously? Puedes darme una referencia fidedigna en la que se indique esto?

Que tiene de malo el ejemplo que me ha puesto Oblivi0n, yo no le veo el fallo, tiene sentido.


Título: Re: Duda direcciones de memoria C
Publicado por: Oblivi0n en 18 Julio 2013, 16:27 pm
Seriously? Puedes darme una referencia fidedigna en la que se indique esto?

http://stackoverflow.com/questions/12626929/pointer-c-declaration (http://stackoverflow.com/questions/12626929/pointer-c-declaration)


Título: Re: Duda direcciones de memoria C
Publicado por: eferion en 18 Julio 2013, 16:28 pm
No me había dado cuenta de ese detalle... también es cierto que evito ese tipo de declaraciones.

bueno ojo OxDani

Código
  1. void main( )
  2. {
  3.  int* a, b;
  4.  
  5.  b = 1;
  6.  a = &b;
  7.  b = a;
  8. }

resultado:

error: C2440: '=' : cannot convert from 'int *' to 'int'
There is no context in which this conversion is possible


Título: Re: Duda direcciones de memoria C
Publicado por: Caster en 18 Julio 2013, 16:28 pm
Código
  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5.    int* px, py;
  6.    int *pz, x=1, y=2, z=3;
  7.  
  8.    px = &x;
  9.    py = &y;
  10.    pz = &z;
  11.  
  12.    printf("%X  %X  %X", px, py, pz);
  13.    printf("\n%d  %d  %d", x, y, z);
  14.    return 0;
  15. }
  16.  

Según este codigo, lo que dice Oblivi0n es verdad


Título: Re: Duda direcciones de memoria C
Publicado por: Oblivi0n en 18 Julio 2013, 16:32 pm
Para programar en C hace falta un poco mas que conocer el lenguaje  ;)


Título: Re: Duda direcciones de memoria C
Publicado por: 0xDani en 18 Julio 2013, 16:36 pm
http://stackoverflow.com/questions/12626929/pointer-c-declaration (http://stackoverflow.com/questions/12626929/pointer-c-declaration)

De ese link:

Código
  1. int* p, p2;  // declares a pointer to int and a regular int
  2. int *p, *p2; // declares two pointers to int

De todas formas, por muy bueno que sea el foro Stack Overflow, no es una referencia fidedigna para este tipo de debates.


Título: Re: Duda direcciones de memoria C
Publicado por: eferion en 18 Julio 2013, 16:40 pm
Para programar en C hace falta un poco mas que conocer el lenguaje  ;)

Yo más bien diría que lo suyo es no optar por código tan peregrino y, visto lo visto, tan propenso a segundas interpretaciones.


Título: Re: Duda direcciones de memoria C
Publicado por: Caster en 18 Julio 2013, 16:43 pm
A ver que no me entero de una, entonces si hacemos esto:

Código
  1. int* ptr1,ptr2,ptr3;

El unico puntero que hay aqui es ptr1, no?


Título: Re: Duda direcciones de memoria C
Publicado por: eferion en 18 Julio 2013, 16:53 pm
Si puedes evitar este tipo de líneas mejor. Por lo que he podido ver en este hilo depende del compilador a utilizar...

En un programa la claridad es un factor clave.

Mejor lo dejas así:

Código
  1. int *ptr1, *ptr2, *ptr3;

Que compila y te quitas de problemas.




Título: Re: Duda direcciones de memoria C
Publicado por: Caster en 18 Julio 2013, 16:54 pm
Vale, muchas gracias


Título: Re: Duda direcciones de memoria C
Publicado por: 0xDani en 18 Julio 2013, 17:09 pm
A ver, al compilar este programa con gcc 4.7.2:

Código
  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5. int* a, b;
  6. int c;
  7.  
  8. b =  &c;
  9.  
  10. printf("0x%x\n", b);
  11.  
  12. return 0;
  13. }

me salta este aviso:


Cita de: gcc
/home/dani/Escritorio/pointers_test.c:8:4: aviso: la asignación crea un entero desde un puntero sin una conversión [activado por defecto]

De lo que se deduce que b es un entero, y no un puntero.

Saludos.


Título: Re: Duda direcciones de memoria C
Publicado por: eferion en 18 Julio 2013, 17:11 pm
A ver, al compilar este programa con gcc 4.7.2:

Código
  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5. int* a, b;
  6. int c;
  7.  
  8. b =  &c;
  9.  
  10. printf("0x%x\n", b);
  11.  
  12. return 0;
  13. }

me salta este aviso:


De lo que se deduce que b es un entero, y no un puntero.

Saludos.

Vale, entonces te pasa lo mismo que a mi compilando con msvc


Título: Re: Duda direcciones de memoria C
Publicado por: 0xDani en 18 Julio 2013, 17:17 pm
Vale, entonces te pasa lo mismo que a mi compilando con msvc

Eso parece  :P


Título: Re: Duda direcciones de memoria C
Publicado por: Caster en 18 Julio 2013, 17:31 pm
Y a mi me pasaba lo mismo.


Título: Re: Duda direcciones de memoria C
Publicado por: dRak0 en 18 Julio 2013, 23:47 pm
Aprovecho el tema q habia iniciado para hacer otra pregunta.
Tengo lo siguiente

Código:
#include <stdio.h>

void funcion1(int);
void funcion2(int);
void funcion3(int);

main()
{
int i;
void (*f[3])(int)={funcion1,funcion2,funcion3};
for(i=0;i<3;i++)
{
(*f[i])(i);
printf(".Direccion en memoria de la funcion:%p",f[i]);
}
}

void funcion1(int a)
{
printf("\nEntro a la funcion 1");
}
void funcion2(int a)
{
printf("\nEntro a la funcion 2");
}
void funcion3(int a)
{
printf("\nEntro a la funcion 3");
}

Queria saber si esta bien lo q afirmo. Es decir , si esta bien de que son las direcciones de memoria de las funciones y no del array. (Supuse que estan bien porque no son consecutivas , pero por las  dudas pregunto).


Título: Re: Duda direcciones de memoria C
Publicado por: rir3760 en 19 Julio 2013, 16:38 pm
A ver que no me entero de una, entonces si hacemos esto:

Código
  1. int* ptr1,ptr2,ptr3;

El unico puntero que hay aqui es ptr1, no?
Correcto. El estándar de C define al lenguaje como uno de formato libre donde el espacio blanco (espacio, tabulador, etc.) solo es significativo en tres casos:
1) Directivas del preprocesador.
2) Cadenas literales.
3) Cuando este indica el final de un token (la unidad mínima que reconoce el lenguaje). Por ejemplo el espacio en "int i;" es significativo mientras que en "int * i;" no lo es (esta ultima se puede separar sin ambigüedades en los tokens 'int', '*', 'i' y ';').

En el ejemplo que mencionas si eliminamos el espacio, los separadores (las comas) y el indicador de fin de sentencia (el punto y coma) los tokens se agrupan así:
Código:
int
*ptr1
ptr2
ptr3
Resultando en la declaración de tres variables donde solo la primera es un puntero.

----

Queria saber si esta bien lo q afirmo. Es decir , si esta bien de que son las direcciones de memoria de las funciones y no del array. (Supuse que estan bien porque no son consecutivas , pero por las  dudas pregunto).
Es correcto, solo un comentario: en el bucle no necesitas aplicar indireccion en la llamada a función y, siendo pesados, no es posible imprimir (de forma portable) la dirección de una función.

La mejor forma en el caso del bucle es:
Código
  1. for (i = 0; i < 3; i++){
  2.   f[i](i);
  3.   printf("La direccion en memoria es %p\n", (void *) f[i]);
  4. }

Un saludo