[C con Clase] Punteros

Steven Davidson steven en conclase.net
Mar Feb 27 00:08:27 CET 2007


Hola Alejandro,

El pasado 2007-02-26 19:24:55, Alejandro escribió:

A> Hola, tengo varias dudas sobre los punteros:
A> ¿Puedo averiguar la dirección de memoria de cualquier cosa de mi ordenador?

Si te refieres a que si puedes manipular el valor guardado en cualquier dirección de memoria, la respuesta es sí. Ahora bien, ten presente que el sistema operativo es quien está al cargo. Tu programa se ejecuta porque el S.O. lo permite. Hoy en día, los SS.OO. son sofisticados e intentan mantener el orden cuanto puedan. Esto implica que si tu programa intenta acceder a zonas de memoria que pudiesen provocar problemas de inestabiliad, entonces el S.O. está en su "derecho" de denegar tal acceso a tu programa. Típicamente, se te enviará un mensaje como "Violación de acceso", "fallo de segmentación", etc..

En resumen, teóricamente y dese el punto de vista de C y C++, puedes acceder a cualquier dirección de memoria que quieras. En la práctica, el sistema operativo es quien cede o niega tal acceso.

A> Si apunto on "int *pA" a un int cualquiera y luego hago: "pA ++;  *pA = 0;" me da un error,¿ por qué?

Esto es porque 'pA' no ha sido inicializada y por tanto contiene "basura". Esto implica que el puntero apunta a cualquier lugar arbitrario, que seguramente no tiene acceso a ello.

La operación 'pA++' es válida, pero no '*pA=0', ya que estamos accediendo a tal memoria y además asignamos un nuevo valor, que posiblemente sustituimos un valor válido que ya existía ahí.

Cualquier sistema operativo "decente" te denegará tal acceso, tanto de lectura como de escritura, si 'pA' apunta a memoria que no te pertenece.

A> ¿Puedo averiguar la dirección de memoria más baja yt la más alta de mi ordenador?

La dirección inferior va a ser 0 (cero), pero todos los ordenadores (o computadoras) usan las primeras direcciones de memoria para guardar información del sistema operativo e incluso de ROM. El valor superior típicamente será el más alto que se puede guardar. Esto sería, 'sizeof(void *)-1'. Si un puntero ocupa 4 bytes, entonces el valor superior seguramente es 4294967295.

Esto no suele ser siempre el caso, por lo que tendrías que usar funciones especiales del sistema operativo para comunicarte con ello y determinar estas características. Obviamente, estas funciones no son estánares y dependen el S.O. que tengas.

A> La más importante, habláis de ellos como algo muy útil, ¿me podéis decir algún ejemplo de uso de punteros?(es que no les veo la utilidad)

Me temo que muchas personas preguntan sobre esto en cuanto ven el tema de punteros. Ciertamente, es un tema muy importante y bastante difícil de entender al principio. No te preocupes si no lo has entendido a la primera, creo que ningún estudiante lo haya hecho, sin saber ensamblador previamente.

Su utilidad se ve mejor al solucionar problemas "avanzados". Típicamente, usamos punteros cuando necesitamos usar memoria dinámica. Esto es, en lugar de usar, por ejemplo, arrays [estáticos] con cantidades fijas, pedimos cierta cantidad de memoria en tiempo de ejecución. Esto crea un programa adaptable, particularmente a las necesidades de memoria. Por ejemplo,

float array[100];
float *pLista=0;
int nCantidad=0;

cout << "Escriba la cantidad de valores: ";
cin >> nCantidad;
pLista = new float[nCantidad];
...

Con 'array', tenemos 100 elementos; ni más ni menos. Con 'pLista' y 'new[]', podemos crear un array dinámico con una cantidad personalizada y adaptada a las necesidades del usuario (en este caso).

Bajo C, usamos punteros para emular el paso por referencia de parámetros a funciones. Como las funciones siempre pasan los valores por copia, no podríamos modificar los valores de esos parámetros entrantes. Al usar punteros, pasamos la copia de la dirección de memoria, la cual sigue apuntando a la misma "variable" y por tanto el valor contenido puede ser modificado. Por ejemplo,

void inc( float *ptr )
{
  ++*ptr;
}

int main()
{
  float num=10.23;

  cout << num << " + 1 = ";
  inc( &num );
  cout << num << endl;

  return 0;
}

Aparecerá en pantalla:
10.23 + 1 = 11.23

C++ introduce la implementación de este concepto de pasar valores por referencia.

Como dije anteriormente, hay que tener cuidado con las direcciones de memoria, ya que si no son válidas, entonces tenemos problemas con el sistema operativo. Sin embargo, bajo ciertas plataformas, tenemos acceso directo a la memoria sin mayores percances. Por ejemplo, con un PC (basado en Intel o compatibles), podemos acceder directamente a la dirección 04000000h para leer 256 bytes que representan información acerca de la BIOS.


Espero que esto aclare las dudas.

Steven


Más información sobre la lista de distribución Cconclase