Punteros en C/C++. En este capítulo nos adentramos en uno de los conceptos más potentes, distintivos y, a la vez, más temidos del lenguaje C, los punteros. Un puntero es una variable especial que almacena la dirección de memoria de otra variable. Esta capacidad hace posible un control directo sobre la memoria, lo que permite una programación muy eficiente aunque también requiere mayor cuidado por parte del programador.
Durante este capítulo veremos:
- ¿Qué es un puntero?
- Declaración, inicialización y uso
- Operadores
*
y&
- Punteros y arrays
- Punteros a funciones
- Punteros dobles y punteros a estructuras
Empezamos!!!
NEWFAST Amplificador Señal WiFi Repetidor WiFi, 300Mbps 2.4GHz Extensor Wi-Fi con 4 Antenas de Alta Ganancia, Amplificador Wi-Fi Puerto LAN, WPS, 4 Modo
4% Fuera6.1 ¿Qué es un puntero?
En los lenguajes C y C++, un puntero es una variable especial que almacena una dirección de memoria. Es decir, no guarda directamente un dato, sino la ubicación en la memoria donde se encuentra ese dato.
Cuando declaras una variable normal, como por ejemplo:
int edad = 30;
Estás reservando una zona de memoria donde se almacenará el valor 30
. Esa zona tiene una dirección, por ejemplo: 0x7ffeebf4a9d8
.
Puedes obtener esa dirección con el operador &
:
printf("%p\n", &edad); // Imprime la dirección de memoria de 'edad'
Un puntero guarda precisamente esa dirección. Lo declaras así:
int *p; // p es un puntero a entero
Ahora puedes hacer que p
apunte a edad
:
p = &edad;
Esto significa: «p contiene la dirección de memoria donde está almacenado el valor de edad.»
Acceso indirecto: desreferenciación (*
)
Si quieres acceder al valor que está en la dirección almacenada por el puntero, usas el operador *
delante del puntero:
printf("%d\n", *p); // Imprime 30, el valor apuntado
Este proceso se llama desreferenciar un puntero: vas a la dirección que contiene y recuperas el dato que hay allí.
Veamos una analogía para entenderlo mejor, imagina que:
- Una variable normal es como una caja con una etiqueta que dice “edad”, y dentro hay un número: 30.
- Un puntero es como una nota que dice: “Ve a la estantería A23 del almacén”. El puntero no tiene el número 30 dentro, sino la ubicación donde puedes ir a buscar ese número.
- Cuando usas
*p
, es como ir físicamente a esa dirección y mirar dentro de la caja.
Veamos un ejemplo básico de como utilizar los punteros.
#include <stdio.h>
int main() {
int edad = 30;
int *ptr;
ptr = &edad;
printf("Valor de edad: %d\n", edad); // 30
printf("Dirección de edad: %p\n", &edad); // 0x.... (ejemplo)
printf("Contenido del puntero ptr: %p\n", ptr); // Igual que &edad
printf("Valor apuntado por ptr: %d\n", *ptr); // 30
return 0;
}
6.2. Declaración, inicialización y uso de punteros en C/C++
Cuando trabajamos con punteros, debemos seguir tres pasos fundamentales y en este orden:
- Declarar el puntero.
- Inicializarlo, es decir, asignarle una dirección válida.
- Usarlo para acceder, modificar o manipular los datos a los que apunta.
Veámoslo cada uno de ellos con más detalle.
– Declaración de punteros
Para declarar un puntero, usamos el operador *
en la declaración. El puntero debe indicar el tipo de dato al que apuntará, ya que esto permite al compilador saber cuántos bytes leer o escribir.
int *ptr; // puntero a entero
float *pfloat; // puntero a float
char *pchar; // puntero a char
@Tip. El asterisco (*
) en el momento de la declaración indica que la variable es un puntero, no que ya esté apuntando a algo.
– Inicialización de punteros
Una vez declarado, un puntero debe contener una dirección válida antes de usarse. Puedes inicializarlo de varias maneras:
A. Asignándole la dirección de una variable existente
int edad = 25;
int *ptr = &edad; // ptr guarda la dirección de 'edad'
B. Inicializándolo con NULL
(puntero nulo)
Esto es útil si no tienes una dirección válida en ese momento. Significa: “no apunta a nada”.
int *ptr = NULL;
Luego puedes asignarle una dirección más adelante:
ptr = &edad;
IMPORTANTE: ¡Nunca uses un puntero sin inicializar!
Si haces uso de un puntero que no has inicializado, este tendrá una dirección de memoria que no se sabe cual puede ser. Esta dirección de memoria puede ser partes críticas de otras partes del programa o del sistema operativo, por lo que si escribimos en él podríamos tener resultados inesperados. Por ese motivo, siempre hay que inicializar los punteros.
int *ptr; // sin inicializar
*ptr = 10; // ERROR: ptr apunta a una dirección aleatoria → comportamiento indefinido
– Uso de punteros
Una vez declarado e inicializado, puedes usar el puntero para acceder o modificar el dato apuntado mediante el operador *
(llamado operador de desreferenciación).
Veamos un ejemplo de c
#include <stdio.h>
int main() {
int edad = 25;
int *ptr = &edad;
printf("Edad original: %d\n", edad); // 25
printf("Desde puntero: %d\n", *ptr); // 25
*ptr = 30; // Cambia el valor de 'edad' a través del puntero
printf("Edad modificada: %d\n", edad); // 30
return 0;
}
Aquí vemos que modificar el valor a través del puntero cambia directamente el contenido de la variable original, porque el puntero actúa sobre la misma zona de memoria.
int x = 10;
int *p;
p = &x; // p guarda la dirección de x
*p = 20; // el valor de x ahora es 20
Variable | Valor | Dirección |
---|---|---|
x | 20 | 0x100 |
p | 0x100 (apunta a x ) | 0x200 |
Recuerda.
Para trabajar correctamente con punteros:
- Siempre inicialízalos con una dirección válida o con
NULL
. - Comprueba si el puntero es
NULL
antes de usarlo (opcional pero recomendable). - Usa
*
solo cuando estás seguro de que el puntero apunta a una dirección válida.
Tabla resumen
Acción | Ejemplo | Explicación |
---|---|---|
Declarar puntero | int *p; | p es un puntero a entero |
Inicializar con dirección | p = &x; | p guarda la dirección de x |
Desreferenciar | *p | Accede o modifica el valor apuntado por p |
6.3 Operadores *
y &
Aunque ya lo hemos visto, vamos a profundizar un poco más en el contexto de los punteros de los operadores *
(asterisco) y &
(ampersand):
&
(operador de dirección): devuelve la dirección de memoria de una variable.*
(operador de desreferenciación): accede al valor almacenado en una dirección de memoria.
Aunque * y & se usan también en otros contextos (por ejemplo, *
en multiplicación o &
en operaciones a nivel de bit), no hay que confundirlos con su uso en el ámbito de los punteros. Su uso es totalmente diferente y es imprescindible tener bien claro cuando y como se utilizan.
Operador &
— Dirección de una variable
El operador &
nos permite obtener la dirección de memoria donde está almacenada una variable.
#include <stdio.h>
int main() {
int x = 42;
printf("El valor de x es: %d\n", x);
printf("La dirección de x es: %p\n", &x); // %p para imprimir direcciones
return 0;
}
En este ejemplo, &x
devuelve algo como 0x7ffeeaa12a3c
, que es la dirección en memoria donde está guardado el valor 42
.
Operador *
— Desreferenciación de un puntero
El operador *
se utiliza para acceder al contenido de la dirección a la que apunta un puntero. Esto se llama desreferenciar un puntero.
Ejemplo:
#include <stdio.h>
int main() {
int x = 42;
int *p = &x;
printf("Valor de x usando puntero: %d\n", *p); // desreferencia p, accede a x
*p = 100; // cambia el valor de x a través del puntero
printf("Nuevo valor de x: %d\n", x); // 100
return 0;
}
*p
accede a lo que hay en la dirección que contiene p
, en este caso, el valor de x
.
Relación entre ambos operadores
&
se usa para obtener una dirección.*
se usa para acceder al valor de esa dirección.
int x = 10;
int *p = &x;
printf("Dirección de x: %p\n", &x); // dirección de x
printf("Contenido de p: %p\n", p); // misma dirección
printf("Valor de x a través de p: %d\n", *p); // 10
Resumen
Código | Significado |
---|---|
int *p; | Declarar p como puntero a entero |
p = &x; | p guarda la dirección de x |
*p = 20; | Modifica el valor apuntado por p (o sea, x ) |
&x | Dirección de x |
*p | Valor al que apunta p |
6.4. Punteros y Arrays en C/C++
En C, los arrays y los punteros están profundamente relacionados. De hecho, un array puede ser tratado como un puntero al primer elemento de la secuencia. Esta relación permite manipular los arrays usando punteros, lo cual es muy útil en programación de bajo nivel o cuando se necesita un mayor control sobre la memoria.
Relación entre Arrays y Punteros
Cuando declaras un array:
int numeros[5] = {10, 20, 30, 40, 50};
Aquí numeros
es en realidad una dirección constante al primer elemento del array. Es decir, numeros
equivale a &numeros[0]
.
Esto significa que puedes hacer:
int *p = numeros;
Ahora p
apunta al primer elemento del array. ¿Y como accedemos a los elementos del array mediante punteros? Pues usando notación de punteros, puedes acceder a los elementos del array como si recorrieras memoria:
#include <stdio.h>
int main() {
int numeros[5] = {10, 20, 30, 40, 50};
int *p = numeros;
for (int i = 0; i < 5; i++) {
printf("Elemento %d: %d\n", i, *(p + i));
}
return 0;
}
Aquí, *(p + i)
accede al valor en la posición i
del array.
Esto es exactamente equivalente a numeros[i]
.
Equivalencias comunes entre arrays y punteros
Notación de array | Notación con punteros | Significado |
---|---|---|
numeros[i] | *(numeros + i) | Elemento en posición i |
&numeros[i] | (numeros + i) | Dirección del elemento i |
p[i] | *(p + i) | Cuando p apunta al array |
Recorrer arrays con punteros
Otra forma de recorrer un array usando punteros es incrementando el puntero directamente:
#include <stdio.h>
int main() {
int numeros[3] = {100, 200, 300};
int *ptr = numeros;
for (int i = 0; i < 3; i++) {
printf("Valor: %d\n", *ptr);
ptr++; // mover al siguiente elemento
}
return 0;
}
⚠️ Importante: No debes incrementar el puntero más allá del tamaño del array, o estarás accediendo a memoria no válida.
Ventajas de usar punteros con arrays
- Permite recorrer arrays sin necesidad de usar índices.
- Permite pasar arrays a funciones y manipular su contenido directamente.
- Permite trabajar con estructuras de datos dinámicas como listas, árboles, etc.
- Hace posible trabajar con subarrays o porciones del array.
Cuidados importantes
- Los arrays no son punteros dinámicos.
- No puedes redimensionar un array estático.
- Su dirección (
numeros
) es constante, no puedes hacernumeros++
.
- Cuidado con la aritmética de punteros:
- Al hacer
p + i
, el incremento se hace en función del tamaño del tipo apuntado (por ejemplo,sizeof(int)
).
- Al hacer
Veamos un ejemplo combinanado punteros y arrays
#include <stdio.h>
void imprimirArray(int *arr, int n) {
for (int i = 0; i < n; i++) {
printf("Elemento %d: %d\n", i, *(arr + i));
}
}
int main() {
int datos[4] = {1, 2, 3, 4};
imprimirArray(datos, 4); // Pasamos el array como puntero
return 0;
}
En este ejemplo, datos
se pasa como puntero a la función, este es el modo en el que trabaja con arrays en funciones en C.
Recuerda
- Un array puede ser tratado como un puntero al primer elemento.
- Puedes acceder a los elementos de un array con notación de puntero:
*(arr + i)
. - Puedes recorrer arrays incrementando punteros.
- Es común pasar arrays a funciones como punteros.
6.5 Punteros a funciones
En C/C++, los punteros a funciones son una característica muy potente que permite almacenar la dirección de una función en una variable. Esto nos abre un abaníco de posibilidades que permite, por ejemplo, pasar funciones como parámetros, implementar callbacks, y diseñar estructuras dinámicas como menús o tablas de operaciones, etc.
A pesar de que su sintaxis puede parecer un poco compleja al principio, el concepto es sencillo: una función también reside en una dirección de memoria, por lo tanto, podemos tener un puntero que la apunte y usar ese puntero para invocar la función.
¿Qué es un puntero a función?
Un puntero a función es una variable que almacena la dirección de memoria de una función, lo que permite llamarla a través del puntero.
La declaración básica es:
tipo_retorno (*nombre_puntero)(tipo_parámetro1, tipo_parámetro2, ...);
Por ejemplo:
int (*operacion)(int, int);
Aquí operacion
es un puntero a una función que recibe dos int
y devuelve un int
.
Veámoslo con un ejemplo
int suma(int a, int b) {
return a + b;
}
int main() {
int (*ptrFuncion)(int, int); // Declaramos el puntero a función
ptrFuncion = suma; // Asignamos la dirección de la función
int resultado = ptrFuncion(4, 5); // Llamamos a la función vía puntero
printf("Resultado: %d\n", resultado);
return 0;
}
Observa que en este caso asignamos dirección de memoria como: ptrFuncion = suma;
y no ptrFuncion = &suma;
— ambas formas son válidas, pero en C la función se convierte automáticamente a puntero al asignarla.
Tabla de operaciones con punteros a funciones
Podemos usar punteros a funciones para construir una especie de “menú” o “tabla” dinámica de operaciones:
#include <stdio.h>
int sumar(int a, int b) { return a + b; }
int restar(int a, int b) { return a - b; }
int multiplicar(int a, int b) { return a * b; }
int main() {
// Array de punteros a funciones
int (*operaciones[3])(int, int) = {sumar, restar, multiplicar};
int x = 10, y = 5;
for (int i = 0; i < 3; i++) {
printf("Resultado operación %d: %d\n", i, operaciones[i](x, y));
}
return 0;
}
Este enfoque permite acceder a diferentes funciones de forma dinámica a través de un índice o puntero.
Pasar funciones como argumentos
Una de las grandes ventajas de los punteros a funciones es que podemos pasarlos como argumentos a otras funciones:
#include <stdio.h>
int operar(int a, int b, int (*f)(int, int)) {
return f(a, b);
}
int sumar(int x, int y) {
return x + y;
}
int main() {
int resultado = operar(3, 7, sumar);
printf("Resultado: %d\n", resultado);
return 0;
}
Esto es útil, por ejemplo, en algoritmos como ordenación, donde podemos pasar funciones de comparación.
Precauciones
- Asegúrate de que la firma de la función coincida exactamente con la declaración del puntero.
- Usar punteros nulos o no inicializados puede causar fallos en tiempo de ejecución.
- Las funciones deben estar declaradas antes de ser usadas como punteros.
Ejemplo con función de comparación
#include <stdio.h>
int mayor(int a, int b) {
return (a > b) ? a : b;
}
int menor(int a, int b) {
return (a < b) ? a : b;
}
void comparar(int x, int y, int (*f)(int, int)) {
printf("Resultado de la comparación: %d\n", f(x, y));
}
int main() {
comparar(10, 20, mayor); // Usamos puntero a función
comparar(10, 20, menor); // Cambiamos el comportamiento
return 0;
}
6.6 Punteros dobles y punteros a estructuras
En este punto avanzamos con dos conceptos clave y avanzados en el manejo de punteros en C/C++:
- Punteros dobles (o punteros a punteros)
- Punteros a estructuras
Ambos son esenciales para trabajar con estructuras dinámicas más complejas como listas enlazadas, matrices dinámicas y estructuras de datos avanzadas.
Punteros Dobles (punteros a punteros)
Un puntero doble es una variable que almacena la dirección de un puntero. Es decir, es un puntero que apunta a otro puntero.
Declaración:
int **ptr;
Aquí ptr
es un puntero que apunta a un puntero a int
.
Veámosolo con un ejemplo:
#include <stdio.h>
int main() {
int valor = 100;
int *p1 = &valor;
int **p2 = &p1;
printf("valor = %d\n", valor); // 100
printf("*p1 = %d\n", *p1); // 100
printf("**p2 = %d\n", **p2); // 100
return 0;
}
**p2
accede al valor original (valor
) a través de dos niveles de indirección: p2 → p1 → valor
.
¿Para qué sirven los punteros dobles?
- Modificar un puntero desde una función:
void asignar(int **pptr) {
*pptr = malloc(sizeof(int));
**pptr = 50;
}
int main() {
int *p = NULL;
asignar(&p);
printf("Valor asignado: %d\n", *p);
free(p);
return 0;
}
– Manejo de matrices dinámicas (matrices 2D)
int **matriz = malloc(filas * sizeof(int *));
for (int i = 0; i < filas; i++) {
matriz[i] = malloc(columnas * sizeof(int));
}
Punteros a estructuras
En C/C++, puedes crear estructuras (struct
) y manipularlas a través de punteros. Esto es muy común en programación de sistemas y estructuras dinámicas.
#include <stdio.h>
struct Persona {
char nombre[20];
int edad;
};
int main() {
struct Persona p1 = {"Carlos", 30};
struct Persona *ptr = &p1;
printf("Nombre: %s\n", ptr->nombre);
printf("Edad: %d\n", ptr->edad);
return 0;
}
@Tip. Observa el uso del operador ->
para acceder a los campos de una estructura a través de un puntero.
Crear estructuras dinámicamente con malloc
malloc
(abreviatura de memory allocation) es una función de la biblioteca estándar de C que se utiliza para reservar memoria dinámica en tiempo de ejecución. Esto significa que puedes pedirle al sistema una cantidad de memoria que no conoces en tiempo de compilación, y la función te devolverá un puntero a la primera dirección del bloque reservado.
Sintaxis:
void *malloc(size_t tamaño_en_bytes);
- Devuelve un puntero
void*
que normalmente se convierte al tipo deseado (int*
,char*
, etc.). - Si la memoria no puede ser reservada, devuelve
NULL
.
Ejemplo:
int *numeros = (int *) malloc(5 * sizeof(int)); // Reserva espacio para 5 enteros
En este caso, malloc
reserva memoria suficiente para almacenar 5 enteros consecutivos y devuelve un puntero al primer elemento.
Es importante liberar esa memoria con
free()
cuando ya no se necesita para evitar fugas de memoria.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Persona {
char nombre[20];
int edad;
};
int main() {
struct Persona *ptr = malloc(sizeof(struct Persona));
strcpy(ptr->nombre, "Lucía");
ptr->edad = 25;
printf("Nombre: %s\n", ptr->nombre);
printf("Edad: %d\n", ptr->edad);
free(ptr);
return 0;
}
Edl uso de malloc es muy útil cuando no conocemos la cantidad de estructuras necesarias en tiempo de compilación.
Combinando punteros dobles y estructuras
Imagina que quieres crear un arreglo dinámico de punteros a estructuras:
struct Persona **grupo = malloc(n * sizeof(struct Persona*));
for (int i = 0; i < n; i++) {
grupo[i] = malloc(sizeof(struct Persona));
strcpy(grupo[i]->nombre, "Persona");
grupo[i]->edad = 20 + i;
}
Esto permite construir arreglos de objetos complejos, como listas de usuarios, productos, etc.
Resumen
Concepto | Descripción |
---|---|
* (un puntero) | Apunta a un valor |
** (puntero doble) | Apunta a un puntero |
-> | Accede a miembros de estructuras vía puntero |
struct *ptr | Puntero a una estructura |
malloc(sizeof(...)) | Asigna memoria dinámica para punteros o estructuras |
Conclusión.
Aquí termina este capítulo, hemos visto uno de los conceptos más potentes y distintivos del lenguaje C/C++: los punteros. Aprendimos que un puntero es una variable que almacena la dirección de memoria de otra variable, lo que permite manipular directamente el contenido de la memoria. Estudiamos cómo se declaran, inicializan y utilizan punteros, haciendo uso de los operadores &
(dirección) y *
(acceso al valor apuntado). Vimos también cómo los punteros se relacionan estrechamente con los arrays, cómo pueden usarse para acceder dinámicamente a sus elementos, y cómo existen punteros a funciones y punteros dobles. Finalmente, introdujimos el uso de la función malloc
para la asignación dinámica de memoria, permitiendo al programa reservar espacio durante la ejecución. Vamos con la parte práctica.
Ejercicio 1 – Copiar un array usando aritmética de punteros
Enunciado:
Escribe un programa que copie los 8 valores de un array origen
en otro array destino
sin usar notación de índices ([i]
). Utiliza exclusivamente aritmética de punteros para recorrer ambos arrays y realizar la copia, y muestra el contenido final de destino
.
Enunciado:
Escribe un programa que copie los 8 valores de un array
origen
en otro array destino
sin usar notación de índices ([i]
). Utiliza exclusivamente aritmética de punteros para recorrer ambos arrays y realizar la copia, y muestra el contenido final de destino
.Código:
#include <stdio.h>
#define N 8
int main(void) {
int origen[N] = {2, 4, 6, 8, 10, 12, 14, 16};
int destino[N];
/* punteros de recorrido */
int *p_src = origen; /* apunta a origen[0] */
int *p_end = origen + N; /* apunta a origen[N] */
int *p_dst = destino; /* apunta a destino[0] */
while (p_src < p_end) { /* recorre hasta la última dirección */
*p_dst = *p_src; /* copia valor */
p_src++; /* avanza en origen */
p_dst++; /* avanza en destino */
}
/* Mostrar destino */
for (p_dst = destino; p_dst < destino + N; p_dst++)
printf("%d ", *p_dst);
return 0;
}
Explicación
p_src
yp_dst
son punteros que avanzan elemento a elemento.p_end
marca la dirección justo después del último elemento deorigen
; cuandop_src
la alcanza termina el bucle.- La copia se hace con
*p_dst = *p_src
, accediendo al valor de cada dirección. - No se usan índices; todo el recorrido se basa en comparar direcciones y desplazarlas con
++
.
Ejercicio 2 – Contar vocales en una cadena con punteros
Enunciado
Pide al usuario una frase de hasta 80 caracteres y cuenta cuántas vocales (mayúsculas o minúsculas) contiene. Recorre la cadena exclusivamente con un puntero; no utilices índices ni funciones de <string.h>
salvo fgets
para la entrada.
Enunciado
Pide al usuario una frase de hasta 80 caracteres y cuenta cuántas vocales (mayúsculas o minúsculas) contiene. Recorre la cadena exclusivamente con un puntero; no utilices índices ni funciones de
<string.h>
salvo fgets
para la entrada.Código:
#include <stdio.h>
#include <ctype.h>
int main(void) {
char frase[81];
int contador = 0;
printf("Introduce una frase: ");
fgets(frase, sizeof(frase), stdin);
/* puntero que recorre la cadena hasta el carácter nulo */
for (char *p = frase; *p != '\0'; p++) {
char c = tolower(*p); /* homogeniza a minúscula */
if (c=='a'||c=='e'||c=='i'||c=='o'||c=='u')
contador++;
}
printf("Número de vocales: %d\n", contador);
return 0;
}
Explicación
fgets
lee la línea completa (incluye espacios).- El puntero
p
avanza carácter a carácter hasta encontrar'\0'
. tolower
normaliza el carácter, así una sola comparación cubre mayúsculas y minúsculas.- Cada coincidencia incrementa
contador
, sin usar índices.
Ejercicio 3 – Matriz dinámica: reserva‑libera y suma de diagonal
Enunciado
Crea dinámicamente una matriz cuadrada N×N
(donde N
lo introduce el usuario), rellénala con los enteros del 1 al N×N
en orden fila‑columna y calcula la suma de la diagonal principal. Utiliza punteros dobles para gestionar la matriz y recuerda liberar toda la memoria reservada.
Enunciado
Crea dinámicamente una matriz cuadrada
N×N
(donde N
lo introduce el usuario), rellénala con los enteros del 1 al N×N
en orden fila‑columna y calcula la suma de la diagonal principal. Utiliza punteros dobles para gestionar la matriz y recuerda liberar toda la memoria reservada.Código:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int N;
printf("Tamaño de la matriz (N): ");
if (scanf("%d", &N) != 1 || N <= 0) {
puts("Valor no válido");
return 1;
}
/* reserva del array de punteros a filas */
int **mat = malloc(N * sizeof(int*));
if (!mat) { puts("Fallo malloc"); return 1; }
/* reserva de cada fila */
for (int i = 0; i < N; i++) {
mat[i] = malloc(N * sizeof(int));
if (!mat[i]) { puts("Fallo malloc"); return 1; }
}
/* rellenar matriz y calcular diagonal */
int valor = 1, sumaDiag = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
mat[i][j] = valor++;
if (i == j) /* posición en diagonal principal */
sumaDiag += mat[i][j];
}
}
printf("Suma diagonal principal: %d\n", sumaDiag);
/* liberar memoria */
for (int i = 0; i < N; i++)
free(mat[i]);
free(mat);
return 0;
}
Explicación
- Reserva dinámica
mat
es un puntero doble (int **
) que primero apunta a un array deN
punteros‑fila.- Cada
mat[i]
apunta a una fila conN
enteros.
- Relleno y cálculo
- Se recorre con dos bucles anidados asignando valores secuenciales.
- Cuando
i==j
, el elemento pertenece a la diagonal principal; se acumula ensumaDiag
.
- Liberación
- Primero se libera cada fila (
free(mat[i])
) y finalmente el array de punteros (free(mat)
), evitando fugas de memoria.
- Primero se libera cada fila (
Bibliografía del tutorial de C/C++.
- C/C++. Curso de programación. Autor: Miguel Angel Acera (Editorial: Anaya Multimedia)
- C/C++. Curso de programación. Autor: Francisco José Ceballos (Editorial: RA-MA)
- Un recorrido por C++. Autor Bjarne Stroustrup (Editorial: Anaya Multimedia)
- 115 Ejercicios resueltos de programación C++. Autor Jorge Fernando Betancourt e Inma Yolanda Polanco (Editorial: RA-MA)