Punteros en C: ¿Qué es la programación con punteros en C? Tipos

¿Qué es el puntero en C?

El sistema puntero en C, es una variable que almacena la dirección de otra variable. También se puede utilizar un puntero para hacer referencia a otra función de puntero. Un puntero se puede incrementar/disminuir, es decir, 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 utilizar punteros en C

Si declaramos una variable v de tipo int, v realmente almacenará un valor.

Cómo utilizar punteros en C

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 signo (&) antes del nombre de la variable.

Cómo utilizar punteros en C

Si imprimes la dirección de una variable en 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 ejemplo de puntero en C.

Cómo utilizar punteros en C

El resultado 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

Ent *y = &v;

VARIABLE PUNTERO
A propuesta de almacenado en un llamado dirección de almacenamiento/memoria A variable que puntos a la dirección de almacenamiento/memoria de una alternativa, variable

Declarar un puntero

Como variables, punteros en Programación en C Deben declararse antes de poder usarse en el programa. Los punteros pueden tener el nombre que se desee siempre que cumplan las reglas de nombres de C. La declaración de un puntero tiene el siguiente formato.

data_type * pointer_variable_name;

Aquí,

  • tipo de datos es el tipo base del puntero de los tipos de variables de C e indica el tipo de variable a la que apunta el puntero.
  • El asterisco (*: el mismo asterisco usado para la multiplicación), que es un operador de indirección, declara un puntero.

Veamos algunas declaraciones de punteros válidas en este tutorial de punteros en 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 las variables estándar con una dirección variable. Si los punteros en la programación en C no se inicializan y se utilizan en un programa, los resultados pueden ser impredecibles y potencialmente desastrosos.

Para obtener la dirección de una variable, utilizamos el operador &, que se coloca antes del nombre de la 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 de punteros:

#include <stdio.h>
int main()
{
   int a=10;    //variable declaration
   int *p;      //pointer variable declaration
   p=&a;        //store address of variable a in pointer p
   printf("Address stored in a variable p is:%x\n",p);  //accessing the address
   printf("Value stored in a variable p is:%d\n",*p);   //accessing the value
   return 0;
}

Salida:

Address stored in a variable p is:60ff08
Value stored in a variable p is:10
Operator Significado
* Tiene 2 propósitos

  1. Declaración de un puntero
  2. Devuelve el valor de la variable referenciada.
& Tiene solo 1 propósito

  • Devuelve la dirección de una variable.

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:

#include <stdio.h>
int main()
{
	int *p = NULL; 	//null pointer
	printf(“The value inside variable p is:\n%x”,p);
	return 0;
}

Salida:

The value inside variable p is:
0

Puntero vacío

In 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 nulo se crea utilizando la palabra clave void. Se puede utilizar para almacenar una dirección de cualquier variable.

El siguiente programa ilustra el uso de un puntero vacío:

#include <stdio.h>
int main()
{
void *p = NULL; 	//void pointer
printf("The size of pointer is:%d\n",sizeof(p));
return 0;
}

Salida:

The size of pointer is:4

puntero salvaje

Se dice que un puntero es un puntero salvaje si no se inicializa con nada. Estos tipos de punteros C no son eficientes porque pueden apuntar a alguna ubicación de memoria desconocida que puede causar problemas en nuestro programa y 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:

#include <stdio.h>
int main()
{
int *p; 	//wild pointer
printf("\n%d",*p);
return 0;
}

Salida:

timeout: the monitored command dumped core
sh: line 1: 95298 Segmentation fault      timeout 10s main

Otros tipos de punteros en 'c' son los siguientes:

  • Puntero colgando
  • Puntero complejo
  • Cerca del puntero
  • 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: utilizamos directamente el nombre de la variable
  • Acceso indirecto: utilizamos un puntero a la variable.

Entendamos esto con la ayuda del programa a continuación.

#include <stdio.h>
/* 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 = 1
Indirect access, var = 1

The address of var = 4202496
The address of var = 4202496

Indirect access, var = 48

Aritmética de punteros en C

Las operaciones del puntero se resumen en la siguiente figura

Aritmética de punteros en C
puntero OperaSupuestos de Alcance

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 dondequiera que se pueda escribir X.

Las siguientes expresiones son equivalentes:

int X =10
int *P = &Y;
For the above code, below expressions are true
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: como los operadores unarios * y ++ se evalúan de derecha a izquierda, sin los paréntesis se incrementaría el puntero P, no el objeto al que apunta P.

La siguiente tabla muestra las operaciones aritméticas y básicas que se pueden utilizar al trabajar con punteros C.

Operadesarrollo Explicación
Asignación entero *P1,*P2
P1=P2;
P1 y P2 apuntan a la misma variable entera
Incremento y decremento Ent *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;

Punteros y matrices C con ejemplos

Tradicionalmente, accedemos a los elementos de la matriz utilizando su índice, pero este método se puede eliminar mediante el uso de punteros. Los punteros facilitan el acceso a cada elemento de la matriz.

#include <stdio.h>
int main()
{
    int a[5]={1,2,3,4,5};   //array initialization
    int *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 elements
        	p++;    //incrementing to the next element, you can also write p=p+1
    }
    return 0;
}

Salida:

1
2
3
4
5

Al sumar un número particular a un puntero, se moverá la ubicación del puntero al valor obtenido mediante una operación de suma. Supongamos que p es un puntero que actualmente apunta a la ubicación de memoria 0, si realizamos la siguiente operación de suma, p+1, se ejecutará de esta manera:

Punteros y matrices C

Suma/incremento de puntero

Dado que p actualmente apunta a la ubicación 0 después de sumar 1, el valor pasará a ser 1 y, por lo tanto, el puntero apuntará a la ubicación de memoria 1.

Punteros C y cadenas 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 <stdio.h>
#include <string.h>
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 pointer
for(int i=0;i<strlen(str);i++)
{
printf("%c\n",*p);
p++;
}
return 0;
}

Salida:

First character is:H
Next character is:e
Printing all the characters in a string
H
e
l
l
o

G
u
r
u
9
9
!

Otra forma de tratar cadenas es con una matriz de punteros como en el siguiente programa:

#include <stdio.h>
int 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;}

Salida:

Please remember these materials:
iron
copper
gold

Ventajas de los punteros en C

  • Los punteros son útiles para acceder a ubicaciones de memoria.
  • Los punteros proporcionan una forma eficaz de acceder a los elementos de una estructura de matriz.
  • Los punteros se utilizan para la asignación dinámica de memoria y para la desasignación.
  • Los punteros se utilizan para formar estructuras de datos complejas, como listas enlazadas, gráficos, árboles, etc.

Desventajas de los punteros en C

  • Los punteros son un poco complejos de entender.
  • Los punteros pueden provocar diversos errores, como fallos 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 provocar daños en 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.

Resum

  • 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 comodín, puntero nulo y otros tipos de punteros.
  • Los punteros se pueden utilizar con matrices y cadenas para acceder a elementos de manera más eficiente.
  • Podemos crear punteros de función para invocar una función dinámicamente.
  • Se pueden realizar operaciones aritméticas en un puntero, lo 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 nulo encasillado.