Lenguaje C

Cada variable de un programa tiene una direcci�n en la memoria del ordenador. Esta direcci�n indica la posici�n del primer byte que la variable ocupa. En el caso de una estructura es la direcci�n del primer campo. En los ordenadores actuales la direcci�n de inicio se considera la direcci�n baja de memoria. Como en cualquier caso las variables son almacenadas ordenadamente y de una forma predecible, es posible acceder a estas y manipularlas mediante otra variables que contenga su direcci�n. A este tipo de variables se les denomina punteros.

Los punteros C son el tipo m�s potente y seguramente la otra clave del �xito del lenguaje. La primera ventaja que obtenemos de los punteros es la posibilidad que nos dan de poder tratar con datos de un tama�o arbitrario sin tener que moverlos por la memoria. Esto puede ahorrar un tiempo de computaci�n muy importante en algunos tipos de aplicaciones. Tambi�n permiten que una funci�n reciba y cambie el valor de una variable. Recordemos que todas las funciones C �nicamente aceptan par�metros por valor. Mediante un puntero a una variable podemos modificarla indirectamente desde una funci�n cualquiera.

Un puntero se declara de la forma: tipo *nombre;

float *pf;
PLANETA *pp;
char *pc;

Para manipular un puntero, como variable que es, se utiliza su nombre; pero para acceder a la variable a la que apunta se le debe preceder de *. A este proceso se le llama indirecci�n. Accedemos indirectamente a una variable. Para trabajar con punteros existe un operador, &, que indica 'direcci�n de'. Con �l se puede asignar a un puntero la direcci�n de una variable, o pasar como par�metro a una funci�n.

void prueba_puntero ( void ) {
  long edad;
  long *p;
  p = &edad;
  edad = 50;
  printf("La edad es %ld\n", edad );
  *p = *p / 2;
  printf("La edad es %ld\n", edad );
}

void imprimir_string ( char string[] ) {
  char *p;
  for ( p = string; *p != '\0'; p++ )
    imprimir_char(*p);
}

Definimos un vector de N_PLA componentes de tipo PLANETA. Este tipo est� formado por un registro. Vemos que en la funci�n de inicializaci�n del vector el puntero a la primera componente se inicializa con el nombre del vector. Esto es una caracter�stica importante de C. La direcci�n de la primera componente de un vector se puede direccionar con el nombre del vector. Esto es debido a que en la memoria del ordenador, los distintos elementos est�n ordenados de forma ascendente. As�, SSolar se puede utilizar como &SSolar[0]. A cada iteraci�n llamamos a una funci�n que nos inicializar� los datos de cada planeta. A esta funci�n le pasamos como argumento el puntero a la componente en curso para que, utilizando la notaci�n ->, pueda asignar los valores adecuados a cada campo del registro. Debemos fijarnos en el incremento del puntero de control de la iteraci�n, p++. Con los punteros se pueden realizar determinadas operaciones aritm�ticas aunque, a parte del incremento y decremento, no son muy frecuentes. Cuando incrementamos un puntero el compilador le suma la cantidad necesaria para que apunte al siguiente elemento de la memoria. Debemos fijarnos que esto es aplicable s�lo siempre que haya distintas variables o elementos situados consecutivamente en la memoria, como ocurre con los vectores.

De forma similar se pueden utilizar funciones que tengan como par�metros punteros, para cambiar el valor de una variable. Veamos:

void intercambio ( void ) {
  int a, b;
  a = 1;
  b = 2;
  swap( &a, &b );
  printf(" a = %d b = %d\n", a, b );
}

void swap ( int *x, int *y ) {
  int tmp;
  tmp = *x;
  *x = *y;
  *y = tmp;
}

La sintaxis de C puede, a veces, provocar confusi�n. Se debe distinguir lo que es un prototipo de una funci�n de lo que es una declaraci�n de una variable. As� mismo, un puntero a un vector de punteros, etc...

  • int f1(); funci�n que devuelve un entero
  • int *p1; puntero a entero
  • int *f2(); funci�n que devuelve un puntero a entero
  • int (*pf)(int); puntero a funci�n que toma y devuelve un entero
  • int (*pf2)(int *pi); puntero a funci�n que toma un puntero a entero y devuelve un entero
  • int a[3]; vector de tres enteros
  • int *ap[3]; vector de tres punteros a entero
  • int *(ap[3]); vector de tres punteros a entero
  • int (*pa)[3]; puntero a vector de tres enteros
  • int (*apf[5])(int *pi); vector de 5 punteros a funci�n que toman un puntero a entero y devuelven un entero.

En los programas que se escriban se debe intentar evitar declaraciones complejas que dificulten la legibilidad del programa. Una forma de conseguirlo es utilizando typedef para redefinir/renombrar tipos.

typedef int *intptr;
typedef intptr (*fptr) ( intptr );
fptr f1, f2;

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
ARTÍCULO ANTERIOR