C/Punteiros
C | ||
← Volver a Enumeracións | Punteiros | Seguir con Nomear tipos → |
Os punteiros son un tipo de variable que non contén un valor ou valores, senón un enderezo de memoria. Neste enderezo de memoria é onde residen os valores, mentres que o punteiro será simplemente un enderezo. Hai que aprender a traballar tanto co valor que contén o punteiro (o enderezo de memoria) como co valor do espazo de memoria sinalado polo punteiro.
Declaración
[editar]Para declarar un punteiro, sitúase na declaración da variable un asterisco, «*
», entre o tipo e mailo identificador da variable. A sintaxe fundamental da declaración dun punteiro é a seguinte:
tipo * identificador;
Onde:
tipo
é o tipo de dato ao que sinala o punteiro,*
sinala que se trata dun punteiro, eidentificador
é o identificador (nome) do punteiro.
Identificador
[editar]Ao elixir identificadores para punteiros, non sería mala idea seguir unha sintaxe fixa que permita ao que lea o código saber que unha variable é un punteiro tan só con ler o seu identificador.
Algúns programadores optan por prefixar ou sufixar os identificadores dos punteiros con algunha combinación de caracteres (coma p
, pt
ou punt
).
Inicialización
[editar]Considérase unha boa práctica inicializar os punteiros co valor nulo (NULL
) para que se saiba que non se reservou aínda espazo en memoria para o enderezo de memoria ao que sinala o punteiro. Isto ademais evita problemas con algunhas funcións, coma realloc()
, usada para traballar con memoria dinámica.
Punteiro a un punteiro
[editar]Se ben a algúns lles resulta difícil comprender isto, pódese declarar un punteiro a un punteiro. Para facelo bastará con engadir á declaración un asterisco adicional. Vexamos un exemplo:
float * * punteiro_a_un_punteiro;
Traballo con punteiros
[editar]Valor nulo
[editar]O valor nulo nos punteiros escríbese NULL
, non 0
. Asignándolle este valor a un punteiro, este deixa de apuntar a un enderezo de memoria. Queda baleiro. Vexamos como se lle dá o valor nulo a un punteiro:
punteiro = NULL;
Tamaño
[editar]O tamaño dos punteiros, o que ocupan en memoria, non ven dado polo tipo de dato especificado na declaración do punteiro. O tipo de dato da declaración corresponde ao tipo de dato ao que sinala o punteiro.
O verdadeiro tamaño do punteiro, posto que o punteiro garda un enderezo de memoria, dependerá da arquitectura do sistema operativo, xa que esta define a forma en que o procesador traballa coa memoria. Así, nun sistema de 32 bits, este será o tamaño do punteiro (32 bits = 4 bytes), e nun de 64 bits o tamaño será de 8 bytes.
Traballar co valor sinalado
[editar]Se queremos traballar ou asignarlle un valor ao espazo de memoria ao que sinala un punteiro (e non ao espazo de memoria que ocupa o punteiro), precédese o identificador do punteiro cun asterisco. Véxanse os seguintes exemplos:
*punteiro = 0; // Asígnaselle o valor 0 ao espazo de memoria sinalado
resultado = *punteiro_ao_primeiro_operando + *punteiro_ao_segundo_operando;
Traballar cos enderezos doutras variables
[editar]Mediante o símbolo «&
» pode obterse o enderezo de memoria dunha variable que non sexa un punteiro, o cal pode resultar moi útil á hora de traballar con punteiros. Véxase o seguinte exemplo:
// Declaramos unha variable de tipo int:
int variable;
// Declaramos unha variable punteiro para recoller o
// enderezo de memoria en que se garda a variable:
int * punteiro;
// Ao choio:
punteiro = &variable;
// Agora "punteiro" sinala ao enderezo de memoria
// en que está gardada "variable".
Punteiros a matrices
[editar]As matrices non son máis que unha forma especial de traballar con punteiros. Unha matriz é en realidade un punteiro cuxo valor (o enderezo de memoria ao que sinala) non pode cambiar, e para o que se reserva un certo espazo en memoria estática ao declaralo ─que dependerá do tipo de datos e a cantidade deles que leve a matriz─.
Se se lle asigna a un punteiro “normal” o enderezo de memoria dunha matriz, poderase traballar co punteiro do mesmo xeito que se fai coa matriz.
Matrices de punteiros
[editar]Pódense declarar matrices de punteiros. Vexamos un exemplo:
char * lista[66];
Isto será unha matriz con 66 celas, cada unha das cales é un punteiro a un dato de tipo carácter (char
).
Operadores
[editar]Hai certos operadores que presentan, para o noso ben, un comportamento lixeiramente distinto cos punteiros do que presentan con outro tipo de variables.
- «
punteiro++
» equivale a «punteiro = punteiro + sizeof(tipo)
». - «
punteiro--
» equivale a «punteiro = punteiro - sizeof(tipo)
». - «
punteiro = punteiro + número
» equivale a «punteiro = punteiro + número * sizeof(tipo)
».
Estes comportamentos especiais para punteiros permiten moverse comodamente por matrices de datos, etc.
- Nota: lémbrese que o “tipo” é o tipo de dato da que sinala o punteiro, xa que o punteiro non ten un tipo definido.
Programa de resumo
[editar]Cómpre comprender por riba o funcionamento do seguinte código, que amosa claramente o principio do funcionamento dos punteiros.
// Ficheiros de cabeceira
#include <stdio.h>
// Para utilizar:
// printf()
#include <stdlib.h>
// Para usar:
// free()
// malloc()
// FUNCIÓN PRINCIPAL
int main(void)
{
// Declaración de variables
int * punteiro;
// Facémoslle espazo en memoria ao enteiro...
punteiro = (int *) malloc(sizeof(int));
// Operacións
*punteiro = 666; // Ao "int" ao que sinala en memoria o punteiro dámoslle o valor 666.
// Impresións en pantalla dos datos interesantes
printf("Punteiro:\n");
printf("\tValor:\t\t%p\n",punteiro); // Valor do punteiro, un enderezo de memoria
printf("\tEnderezo:\t\t%p\n",&punteiro); // Enderezo de memoria en que se garda o punteiro
printf("\tTamaño:\t\t%d bytes\n",sizeof(punteiro));
printf("Espazo de memoria apuntado:\n");
printf("\tValor:\t\t%d\n",*punteiro); // Valor ao que sinala o punteiro
printf("\tEnderezo:\t\t%p\n",&(*punteiro)); // Enderezo, que debería coincidir co valor do punteiro
printf("\tTamaño:\t\t%d bytes\n",sizeof(*punteiro));
// Liberamos a memoria reservada para o punteiro (este paso é obrigatorio)
free(punteiro);
// Saída normal do programa
return 0;
}
O programa debería permitirnos comprender a diferencia entre o punteiro e o dato ao que apunta. Cómpre copiar o código nun ficheiro de texto, compilalo e executalo. Un posible resultado sería o seguinte:
Punteiro: Valor: 0x1104010 Enderezo: 0x7fff9f9b42e8 Tamaño: 8 bytes Espazo de memoria apuntado: Valor: 666 Enderezo: 0x1104010 Tamaño: 4 bytes
Véxase tamén
[editar]stdlib.h
contén funcións para traballar con punteiros e a memoria dinámica.
C | ||
← Volver a Enumeracións | Punteiros | Seguir con Nomear tipos → |