oct 07
Programació bàsica (Punters)
Una cosa complicada d'entendre a C són els punters, així que miraré de que quedi clar que són però no sé si me'n sortiré
La primera pregunta que ens hauríem de fer és, què és un punter? Un punter és un variable que apunta a una direcció de memòria, pot ser del tipus que sigui la dada emmagatzemada. El punter ens dona molt de joc amb els programes que fem, doncs ens permet treballar amb variables que no pertanyen a la nostra funció i modificar-les des de la mateixa funció.
M'explico. En els nostres programes, com a principi, la definició de les variables la farem dintre de la funció on s'empri dita variable, i mai com a variables globals (Una variable global és una variable que pot ser accedida per qualsevol funció a sac, però això no sempre és bo i com a bona pràctica de programació es desaconsella el seu ús). Com hem vist abans els funcions només ens retornen un valor, del tipus que sigui, però només un. Això és una limitació important a quan es vol, o es necessita, que una funció modifiqui diversos canvis de variables.
Com he dit abans els punters són adreces de memòria. Entenem que la memòria a la que el programa accedeix és la de la màquina. Com vaig dir al tema de funcions al passar-se una variable el que realment es fa és copiar-la, pel que l'original no es veu modificada en cap moment. En canvi si emprem un punter el que farem és passar-li l'adreça de memòria on està guardada la variable original, amb el que els canvis que fem a la funció afectaran directament a l'adreça original. Això s'anomena passar una variable per referència i es fa de la següent manera:
resultat=funcio(var1,var2,&var3);
Aquí podem veure que funció retorna un valor que és emmagatzemat a resultat, però var3 té un & estrany davant. Aquest símbol el que fa és incidar que passem l'adreça de memòria on està guardada var3.
Ara mirem com queda la definició de la funció:
int funcio (int var1, int var2, int *var3)
{
*var3 = var1+var2;
return var1-var2;
}
Com podeu veure aquesta funcio, que hem anomenat "funcio", retorna la resta de var1 menys var2, però modifica també el valor de var3, canvi que seguirà present quan sortim de la funció. Davant de var3 ara he posat un * (punter), aquest símbol el que fa és accedir al contingut d'on apunta l'adreça de memòria. És a dir, si fèssim un "printf ("%d",var3);" el que veuríem no seria el valor de var3, sinó l'adreça de memòria on estan guardades les dades, per mostrar les dades de var3 hauríem de fer: "printf ("%d",*var3);
És una mica farregosa la nomenclatura, però molt potent.
A més es pot crear un punter directament, aquí l'empràvem com a 'eina' però podem crear un punter i llavors demanar memòria per al tipus de dada que vulguem que emmagatzemi. Penseu que fins ara només hem vist com treballar amb estructures estàtiques, és a dir, si defineixo int numeros[1000]; vol dir que números té caselles per guardar 1000 números de tipus int, però si ens passem tenim moltes possibilitats de que el programa rebenti o ens agafi 'porqueria' a la memòria que tenim més enllà de les dimensions que hem delimitat per números. En canvi si tenim una llista que volem que sigui d'"infinites" entrades haurem d'emprar punters i anar-els-hi creant la memòria a mesura que els entrem.
Això ho veig un xic més complex així que només posaré un parell d'exemples de demanar memòria però es veurà en més detall quan parli de tipus d'estructures d'emmagatzamament, més endevant.
Declarem un punter d'un tipus:
int *molts;
Ara demanem memòria per a la dada:
molts=(int *)malloc(sizeoff(int));
Amb aquesta crida demanem espai de memòria amb malloc per a un punter de tipus int, el principi, amb la mida, això ho fem amb el sizeoff, d'int. Això ho podem fer amb qualsevol tipus de dada, siguin ja definides o estructures que creem nosaltres.
