¿Qué es el puntero en C?
El puntero en C, es una variable que almacena la dirección de otra variable. Un puntero también se puede utilizar para hacer referencia a otra función de puntero. Un puntero se puede incrementar / disminuir, es decir, para apuntar a la ubicación de memoria siguiente / anterior. El propósito del puntero es ahorrar espacio en la memoria y lograr un tiempo de ejecución más rápido.
Cómo usar punteros en C
Si declaramos una variable v de tipo int, v realmente almacenará un valor.
v es igual a cero ahora.
Sin embargo, cada variable, además del valor, también tiene su dirección (o, simplemente, dónde se encuentra en la memoria). La dirección se puede recuperar poniendo un ampersand (&) antes del nombre de la variable.
Si imprime la dirección de una variable en la pantalla, se verá como un número totalmente aleatorio (además, puede ser diferente de una ejecución a otra).
Probemos esto en la práctica con el puntero en el ejemplo de C
La salida de este programa es -480613588.
Ahora bien, ¿qué es un puntero? En lugar de almacenar un valor, un puntero almacenará la dirección de una variable.
Variable de puntero
Int * y = & v;
VARIABLE |
PUNTERO |
Un valor almacenado en una dirección de memoria / almacenamiento con nombre |
Una variable que apunta a la dirección de almacenamiento / memoria de otra variable |
Declarar un puntero
Al igual que las variables, los punteros en la programación en C deben declararse antes de que puedan usarse en su programa. Los punteros pueden tener el nombre que desee siempre que obedezcan las reglas de denominación de C. Una declaración de puntero tiene la siguiente forma.
data_type * pointer_variable_name;
Aquí,
- data_type es el tipo base del puntero de los tipos de variable de C e indica el tipo de variable a la que apunta el puntero.
- El asterisco (*: el mismo asterisco utilizado para la multiplicación) que es un operador de indirección, declara un puntero.
Veamos algunas declaraciones de puntero válidas en este tutorial de punteros de C:
int *ptr_thing; /* pointer to an integer */int *ptr1,thing;/* ptr1 is a pointer to type integer and thing is an integer variable */double *ptr2; /* pointer to a double */float *ptr3; /* pointer to a float */char *ch1 ; /* pointer to a character */float *ptr, variable;/*ptr is a pointer to type float and variable is an ordinary float variable */
Inicializar un puntero
Después de declarar un puntero, lo inicializamos como variables estándar con una dirección de variable. Si los punteros en la programación C no están sin inicializar y se utilizan en el programa, los resultados son impredecibles y potencialmente desastrosos.
Para obtener la dirección de una variable, usamos el operador comercial (&), colocado antes del nombre de una variable cuya dirección necesitamos. La inicialización del puntero se realiza con la siguiente sintaxis.
Sintaxis del puntero
pointer = &variable;
A continuación se proporciona un programa sencillo para la ilustración del puntero:
#includeint main(){int a=10; //variable declarationint *p; //pointer variable declarationp=&a; //store address of variable a in pointer pprintf("Address stored in a variable p is:%x\n",p); //accessing the addressprintf("Value stored in a variable p is:%d\n",*p); //accessing the valuereturn 0;}
Producción:
Address stored in a variable p is:60ff08Value stored in a variable p is:10
Operador | Sentido |
* | Sirve para 2 propósitos
|
Y | Sirve solo para un propósito
|
Tipos de punteros en C
A continuación se muestran los diferentes tipos de punteros en C :
Puntero nulo
Podemos crear un puntero nulo asignando un valor nulo durante la declaración del puntero. Este método es útil cuando no tiene ninguna dirección asignada al puntero. Un puntero nulo siempre contiene el valor 0.
El siguiente programa ilustra el uso de un puntero nulo:
#includeint main(){int *p = NULL; //null pointerprintf(“The value inside variable p is:\n%x”,p);return 0;}
Producción:
The value inside variable p is:0
Puntero vacío
En la programación en C, un puntero vacío también se denomina puntero genérico. No tiene ningún tipo de datos estándar. Un puntero vacío se crea utilizando la palabra clave void. Puede usarse para almacenar una dirección de cualquier variable.
El siguiente programa ilustra el uso de un puntero vacío:
#includeint main(){void *p = NULL; //void pointerprintf("The size of pointer is:%d\n",sizeof(p));return 0;}
Producción:
The size of pointer is:4
Puntero salvaje
Se dice que un puntero es un puntero salvaje si no se inicializa a nada. Estos tipos de punteros C no son eficientes porque pueden apuntar a una ubicación de memoria desconocida que puede causar problemas en nuestro programa y puede provocar que el programa se bloquee. Siempre se debe tener cuidado al trabajar con punteros salvajes.
El siguiente programa ilustra el uso del puntero salvaje:
#includeint main(){int *p; //wild pointerprintf("\n%d",*p);return 0;}
Producción
timeout: the monitored command dumped coresh: line 1: 95298 Segmentation fault timeout 10s main
Otros tipos de punteros en 'c' son los siguientes:
- Puntero colgante
- Puntero complejo
- Puntero cercano
- Puntero lejano
- Puntero enorme
Punteros de acceso directo e indirecto
En C, hay dos formas equivalentes de acceder y manipular un contenido variable
- Acceso directo: usamos directamente el nombre de la variable
- Acceso indirecto: usamos un puntero a la variable
Entendamos esto con la ayuda del programa a continuación
#include/* Declare and initialize an int variable */int var = 1;/* Declare a pointer to int */int *ptr;int main( void ){/* Initialize ptr to point to var */ptr = &var;/* Access var directly and indirectly */printf("\nDirect access, var = %d", var);printf("\nIndirect access, var = %d", *ptr);/* Display the address of var two ways */printf("\n\nThe address of var = %d", &var);printf("\nThe address of var = %d\n", ptr);/*change the content of var through the pointer*/*ptr=48;printf("\nIndirect access, var = %d", *ptr);return 0;}
Después de compilar el programa sin errores, el resultado es:
Direct access, var = 1Indirect access, var = 1The address of var = 4202496The address of var = 4202496Indirect access, var = 48
Aritmética de puntero en C
Las operaciones del puntero se resumen en la siguiente figura
Operación prioritaria (precedencia)
Al trabajar con punteros C, debemos observar las siguientes reglas de prioridad:
- Los operadores * y & tienen la misma prioridad que los operadores unarios (¡la negación !, el incremento ++, el decremento--).
- En la misma expresión, los operadores unarios *, &,!, ++, - se evalúan de derecha a izquierda.
Si un puntero P apunta a una variable X, entonces * P se puede usar siempre que se pueda escribir X.
Las siguientes expresiones son equivalentes:
int X = 10 int * P = & Y; Para el código anterior, las siguientes expresiones son verdaderas | |
Expresión | Expresión equivalente |
Y = * P + 1 * P = * P + 10 * P + = 2 ++ * P (* P) ++ | Y = X + 1 X = X + 10 X + = 2 ++ X X ++ |
En el último caso, se necesitan paréntesis: dado que los operadores unarios * y ++ se evalúan de derecha a izquierda, sin los paréntesis se incrementaría el puntero P, no el objeto en el que P apunta.
La siguiente tabla muestra la operación aritmética y básica que se puede utilizar cuando se trabaja con punteros C
Operación | Explicación |
Asignación | int * P1, * P2 P1 = P2; P1 y P2 apuntan a la misma variable entera |
Incrementacion y decrementacion | Int * P1; P1 ++; P1--; |
Agregar un desplazamiento (constante) | Esto permite que el puntero mueva N elementos en una tabla. El puntero aumentará o disminuirá N veces el número de bytes del tipo de variable. P1 + 5; |
C punteros y matrices con ejemplos
Tradicionalmente, accedemos a los elementos de la matriz usando su índice, pero este método se puede eliminar usando punteros. Los punteros facilitan el acceso a cada elemento de la matriz.
#includeint main(){int a[5]={1,2,3,4,5}; //array initializationint *p; //pointer declaration/*the ptr points to the first element of the array*/p=a; /*We can also type simply ptr==&a[0] */printf("Printing the array elements using pointer\n");for(int i=0;i<5;i++) //loop for traversing array elements{printf("\n%x",*p); //printing array elementsp++; //incrementing to the next element, you can also write p=p+1}return 0;}
Producción
12345
Agregar un número particular a un puntero moverá la ubicación del puntero al valor obtenido por una operación de suma. Supongamos que p es un puntero que apunta actualmente a la ubicación de memoria 0 si realizamos la siguiente operación de suma, p + 1 entonces se ejecutará de esta manera:
Dado que p actualmente apunta a la ubicación 0 después de sumar 1, el valor se convertirá en 1 y, por lo tanto, el puntero apuntará a la ubicación de memoria 1.
Punteros y cadenas de C con ejemplos
Una cadena es una matriz de objetos char que termina con un carácter nulo '\ 0'. Podemos manipular cadenas usando punteros. Este puntero en el ejemplo de C explica esta sección
#include#include int main(){char str[]="Hello Guru99!";char *p;p=str;printf("First character is:%c\n",*p);p =p+1;printf("Next character is:%c\n",*p);printf("Printing all the characters in a string\n");p=str; //reset the pointerfor(int i=0;i Producción
First character is:HNext character is:ePrinting all the characters in a stringHelloGuru99!Otra forma de tratar cadenas es con una matriz de punteros como en el siguiente programa:
#includeint main(){char *materials[ ] = { "iron", "copper", "gold"};printf("Please remember these materials :\n");int i ;for (i = 0; i < 3; i++) {printf("%s\n", materials[ i ]);}return 0;} Producción:
Please remember these materials:ironcoppergoldVentajas de los punteros en C
- Los punteros son útiles para acceder a las ubicaciones de la memoria.
- Los punteros proporcionan una forma eficaz de acceder a los elementos de una estructura de matriz.
- Los punteros se utilizan tanto para la asignación dinámica de memoria como para la desasignación.
- Los punteros se utilizan para formar estructuras de datos complejas, como listas vinculadas, gráficos, árboles, etc.
Desventajas de los punteros en C
- Los punteros son un poco complejos de entender.
- Los punteros pueden provocar varios errores, como fallas de segmentación, o pueden acceder a una ubicación de memoria que no es necesaria en absoluto.
- Si se proporciona un valor incorrecto a un puntero, puede dañar la memoria.
- Los punteros también son responsables de la pérdida de memoria.
- Los punteros son comparativamente más lentos que los de las variables.
- A los programadores les resulta muy difícil trabajar con los punteros; por lo tanto, es responsabilidad del programador manipular un puntero con cuidado.
Resumen
- Un puntero no es más que una ubicación de memoria donde se almacenan los datos.
- Se utiliza un puntero para acceder a la ubicación de la memoria.
- Hay varios tipos de punteros, como puntero nulo, puntero salvaje, puntero vacío y otros tipos de punteros.
- Los punteros se pueden usar con matriz y cadena para acceder a los elementos de manera más eficiente.
- Podemos crear punteros de función para invocar una función de forma dinámica.
- Las operaciones aritméticas se pueden realizar en un puntero que se conoce como aritmética de puntero.
- Los punteros también pueden apuntar a funciones, lo que facilita la llamada a diferentes funciones en el caso de definir una matriz de punteros.
- Cuando desee tratar diferentes tipos de datos variables, puede utilizar un puntero vacío encasillado.