Docsity
Docsity

Prepara i tuoi esami
Prepara i tuoi esami

Studia grazie alle numerose risorse presenti su Docsity


Ottieni i punti per scaricare
Ottieni i punti per scaricare

Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium


Guide e consigli
Guide e consigli


Appunti su Sottoprogrammi e puntatori - Programmazione C, Appunti di Elementi di Informatica

Appunti chiari e sintetici sulle funzioni (o sottoprogrammi) e i puntatotori, arricchiti con esempi guidati. Argomenti: Sottoprogrammi, Record di attivazione, Passaggio di strutture dati dinamiche (array, struct), puntatori, aritmetica dei puntatori.

Tipologia: Appunti

2013/2014

In vendita dal 17/04/2014

rickystream94
rickystream94 🇮🇹

6 documenti

1 / 10

Toggle sidebar

Questa pagina non è visibile nell’anteprima

Non perderti parti importanti!

bg1
I sottoprogrammi possono essere scritti sia prima che dopo il main, ma prima di esso va dichiarato il
PROTOTIPO del sottoprogramma nella forma:
<tipo_dato_restituito_tramite_return> nomesottoprogramma ( <elenco_informazioni_scambiate> );
Esempio: int sceltamenu ( );
Utilità dei sottoprogrammi: scomporre un programma complesso in diversi mini problemi più facilmente
risolubi li.
Lo schema generale di un programma in C quindi diventa:
#include…
#define…
typedef { }
[prototipi sottoprogrammi (dichiarazione)]
[sottoprogrammi (definizione)]
Non è necessario specificare oltre al tipo anche il nome della variabile in ingresso nei prototipide i
sottoprogrammi, cosa invece necessaria nella loro definizione.
Regole di visibilità
Una variabile esiste solo all'interno del blocco in cui è stata definita (main o sottoprogrammi);
Una variabile dichiarata all'inte rno di un blocco (main o sottoprogrammi) viene definita locale;
Esempio: scrivere sottoprogramma stampamenu, di seguito, sceltamenu infine vocemenu:
Nota: Tra le parentesi può anche non esserci nulla, in questo caso significa che il sottoprogramma
non riceve nulla in ingresso. Allo stesso modo, può non restituire alcun dato, in questo caso il
"niente" si traduce con void. Inoltre è sbagliatoscrivere all'interno delle parentesi int a,bma
per ogni variabile bisogna specificarne il tipo: int a, int b.
N.B. Il signifi cato del return alla fine del
codice quindi è quello di indicare che cosa
restituirà quel programma. Nei programmi il
return 0; indica che il programma non
restituisce nulla (ovvero è concluso), mentre
nel caso dei sottoprogrammi esso è solito
indicare una variabile, o nel caso di void non è
seguito da altre informazioni prima del ;
Sottoprogrammi e puntatori
lunedì 2 di cembre 2013
23.40
Fondamenti Informatica Page 1
pf3
pf4
pf5
pf8
pf9
pfa

Anteprima parziale del testo

Scarica Appunti su Sottoprogrammi e puntatori - Programmazione C e più Appunti in PDF di Elementi di Informatica solo su Docsity!

I sottoprogrammi possono essere scritti sia prima che dopo il main , ma prima di esso va dichiarato il PROTOTIPO del sottoprogramma nella forma: <tipo_dato_restituito_tramite_return> nomesottoprogramma ( <elenco_informazioni_scambiate> ); Esempio: int sceltamenu ( ); Utilità dei sottoprogrammi: scomporre un programma complesso in diversi mini problemi più facilmente risolubili. Lo schema generale di un programma in C quindi diventa: #include… #define… typedef { } [prototipi sottoprogrammi ( dichiarazione )] Int main (…) { } [sottoprogrammi ( definizione )] Non è necessario specificare oltre al tipo anche il nome della variabile in ingresso nei prototipi dei sottoprogrammi, cosa invece necessaria nella loro definizione. Regole di visibilità

  • Una variabile esiste solo all'interno del blocco in cui è stata definita (main o sottoprogrammi);
  • Una variabile dichiarata all'interno di un blocco (main o sottoprogrammi) viene definita locale ; Esempio: scrivere sottoprogramma stampamenu, di seguito, sceltamenu infine vocemenu: Nota: Tra le parentesi può anche non esserci nulla, in questo caso significa che il sottoprogramma non riceve nulla in ingresso. Allo stesso modo, può non restituire alcun dato, in questo caso il "niente" si traduce con void. Inoltre è sbagliato scrivere all'interno delle parentesi int a,b ma per ogni variabile bisogna specificarne il tipo: int a, int b. N.B. Il significato del return alla fine del codice quindi è quello di indicare che cosa restituirà quel programma. Nei programmi il return 0; indica che il programma non restituisce nulla (ovvero è concluso), mentre nel caso dei sottoprogrammi esso è solito indicare una variabile, o nel caso di void non è seguito da altre informazioni prima del ;

Sottoprogrammi e puntatori

lunedì 2 dicembre 2013

Prima si svolge il main , poi i sottoprogrammi di servizio. Un esempio valido è un sottoprogramma che calcola e restituisce il fattoriale di un numero intero: Ma nel caso sopra riportato il programma non considera casi di n negativi: Il risultato definitivo è quanto segue: Parametro formale (si definiscono formali quei parametri dichiarati nel sottoprogramma che assumono il valore dei rispettivi parametri attuali utilizzati nel programma) Parametri attuali (sono i parametri il cui valore viene copiato nei parametri formali del sottoprogramma)

Sottoprogrammi

martedì 3 dicembre 2013

Record di Attivazione (RDA)

A ogni attivazione di un sottoprogramma è richiesta l'associazione di un'area dati e non è noto a priori quante volte un sottoprogramma verrà chiamato durante l'esecuzione, perciò l'allocazione dell'area dati deve avvenire necessariamente durante l'esecuzione del programma e non da parte del compilatore, con conseguente perdita di efficienza. Tuttavia tale perdita di efficienza può essere notevolmente limitata sfruttando la disciplina LIFO (Last In Fist Out) delle chiamate dei sottoprogrammi. La prima esecuzione che termina, in una catena di chiamate dei sottoprogrammi, è sempre quella relativa all'ultima chiamata. Quest'organizzazione della memoria viene definita con una struttura chiamata stack (= pila) e rappresenta un'area di memoria diversa da quella dove sta il programma main e tutti i sottoprogrammi, ed è dedicata proprio alla creazione di uno spazio necessario per scambiare le informazioni tra questi. Ogni area dati, detta record di attivazione , associata a ogni chiamata di sottoprogramma, viene allocata in una zona contigua a quella immediatamente precedente: tale contiguità tra i record di attivazione non verrà mai violata proprio grazie al fatto che nessun'area dati sarà cancellata prima di una allocata dopo di essa (immagina una pila di piatti: ogni piatto nuovo viene depositato sulla cima della pila ed è il primo ad essere prelevato da essa). La dimensione dello stack è finita (determinata, quindi c'è un limite massimo oltre il quale non può crescere).

  • le variabili statiche ;
  • l’area heap disponibile per allocazioni dinamiche (spiegata bene in seguito)
  • l’area stack che contiene i record di attivazione delle procedure/funzioni. Si ricorda che a ciascun programma utente viene assegnata una porzione di memoria, che è automaticamente divisa in due parti; l’area del codice contiene il codice del programma, mentre l’ area dati contiene: In base a quanto detto, è possibile riassumere i seguenti concetti.
  • varia da una funzione/procedura all’altra; ma, per una data funzione/procedura, è fissa e calcolabile a priori.
  1. La dimensione del record di attivazione : viene creato nello stack dinamicamente nel momento in cui la funzione/procedura viene chiamata;

rimane nello stack per tutto il tempo in cui la funzione/procedura è in esecuzione;

viene deallocato (rilasciato) alla fine quando la funzione/procedura termina.

  1. Il record di attivazione :
    • allocati secondo l’ordine delle chiamate;
    • deallocati in ordine inverso. Funzioni/procedure che chiamano altre funzioni/procedure danno luogo a una sequenza di record di attivazione:

Sottoprogrammi

mercoledì 11 dicembre 2013 19:

l’ indirizzo di ritorno , ossia l’indirizzo della prossima istruzione del chiamante che andrà eseguita quando la funzione/procedura termina;

il link dinamico , ossia l’indirizzo di memoria del record di attivazione del chiamante, in modo da poter ripristinare l’ambiente del chiamante quando la funzione/procedura termina.

Quando la funzione/procedura termina, il controllo torna al chiamante, che deve riprendere la sua esecuzione dall'istruzione successiva alla chiamata della funzione/procedura e trovare il suo “mondo” inalterato. Per “mondo” si intende l’insieme delle informazioni contenute nel record di attivazione dello stesso chiamante (ad esempio variabili locali e parametri formali). Al fine di permettere al programma chiamante di riprendere dalla prima istruzione successiva alla chiamata alla procedura/funzione e di recuperare l’intero record di attivazione, dopo la conclusione della procedura/funzione chiamata, si inseriscono nel record di attivazione della funzione anche: Il RDA è quindi un insieme di informazioni di base che fanno si che io possa chiamare un sottoprogramma, eseguirne il codice, ritornare al programma e continuare quel che stavo facendo. N.B. Bisogna stare attenti a non chiamare troppi sottoprogrammi, perché appunto la memoria stack è finita, quindi si rischia di ottenere uno stack overflow. Una serie di inefficienze rendono il programma lento. In sostanza il RDA ci consente proprio il passaggio da un programma (o sottoprogramma) chiamante e il sottoprogramma chiamato. Quando torno da un sottoprogramma (come nel caso sopra) le variabili i e j non esistono più! Tutto ciò che dichiaro nel sottoprogramma viene utilizzato esclusivamente da esso.

Sottoprogrammi

giovedì 12 dicembre 2013 17:

  • Stringhe Esercizio: Scrivere il sottoprogramma che ricevuta in ingresso una stringa, restituisce la sua lunghezza. Il sottoprogramma appena scritto è molto frequente e il suo prototipo è: size_of strlen(char[]) Nel main questa funzione viene quindi chiamata in questo modo: l=strlen(s); N.B. La funzione strlen rientra nelle funzioni di libreria incluse in <string.h> perciò non è necessario dichiararla e nemmeno definirla per poterla chiamare nel main!
  • Struct (necessita la conoscenza dei puntatori a pag. 8) Le strutture possono essere passate ad un sottoprogramma per valore o per indirizzo; Importante! Una struttura può essere passata per valore anche quando contiene un componente di tipo array. Il sottoprogramma può restituire per valore o per indirizzo una struttura (anche quando contiene un componente di tipo array), tuttavia il passaggio per valore di una struttura molto grande o di una struttura contenente array può risultare particolarmente inefficiente e dispendiosa dal punto di vista dell'ingombro di memoria. In dettaglio: si potrebbe accedere alla componente x della struttura t_elemento cui il puntatore punta tramite la notazione: (*puntatore).x Ma il C fornisce una notazione più sintetica e perfettamente equivalente alla precedente: puntatore - > x Questa notazione usa l'operatore - > fornito dal linguaggio per accedere al membro di una struttura attraverso una variabile che punta alla struttura stessa. Perciò: La stringa non rientra nelle strutture dati particolari passate ai sottoprogrammi, e infatti non è necessario far sapere al sottoprogramma la lunghezza della stringa definita con la define nel main poiché con le stringhe si lavora sempre con il terminatore! Si può notare che abbiamo creato una struttura chiamata t_elemento e un puntatore ad un dato di tipo t_elemento; per accedere ai membri interni della struttura “t_elemento” abbiamo usato l’operatore - > sul puntatore alla struttura.

Sottoprogrammi

venerdì 13 dicembre 2013 16:

Che cos'è un puntatore? Ogni dato viene rappresentato in memoria come una sequenza di bit e gli viene assegnato un indirizzo. Il tipo di dato puntatore permette di dichiarare una variabile che contiene come valore un indirizzo di memoria di un'altra variabile. Ad esempio, la dichiarazione: int *puntatore; definisce la variabile puntatore come un puntatore a una cella contenente un valore di tipo int , quindi il valore di puntatore è l'indirizzo di un'altra variabile, in questo caso di tipo int. Sintassi Dichiarazione: tipoVariabilePuntata *nomePuntatore; Assegnazione: nomePuntatore = &altraVariabile; Utilizzo: variabile = *nomePuntatore; Dichiarazione : L'accesso ad una variabile "puntata" dal puntatore avviene mediante l'operatore di dereferenziazione , indicato dal simbolo ***** posto prima dell'identificatore del puntatore.

Precisamente *puntatore indica la cella di memoria il cui indirizzo è memorizzato in puntatore. Questo operatore quindi restituisce il contenuto dell'oggetto puntato dal puntatore; Assegnazione : I puntatori possono essere a loro volta oggetto di assegnamento, essendo essi stessi variabili. E' possibile estrarre l'indirizzo del dato contenuto da una variabile tramite l'operatore & (indirizzo di). Questo operatore quindi restituisce l'indirizzo della variabile.

Utilizzo : Per accedere al dato di cui conosciamo l'indirizzo si utilizza l'operatore di dereferenziazione '*'; pertanto *var_Punt restituisce il dato puntato da var_Punt.

Puntatori e funzioni Partiamo con un esempio. Se volessi creare il sottoprogramma che scambi il valore di 2 variabili: Poter passare ad una funzione dati di grosse dimensioni (es. vettore o matrice) senza doverla ricopiare;

  • Possibilità di modificare il valore delle variabili nel programma; Scrivere funzioni che restituiscano più di un valore: come? Passando, per indirizzo, in ingresso alla funzione anche le variabili del programma che devono contenere una risposta.

Vantaggi del passaggio per indirizzo Applicare un sottoprogramma del genere non produrrebbe alcun cambiamento reale alle variabili del programma! Infatti verrebbe solamente copiato il valore dei parametri attuali nelle variabili locali del sottoprogramma. L'utilizzo dei puntatori permette di risolvere questo problema, permettendo il passaggio dei parametri per indirizzo e non più per valore. Attraverso questo passaggio viene passato solamente un puntatore al dato.

Puntatori

giovedì 12 dicembre 2013 11:

Se p e q puntano a due diversi elementi di un array, p - q restituisce un valore intero pari al numero di elementi esistenti tra l'elemento cui punta p e l'elemento cui punta q. E' bene prestare attenzione al fatto che tale differenza non coincide con la differenza tra il valore dei puntatori. Supponendo infatti che il risultato di p - q sia pari a 3 (cioè che esistano 3 elementi dell'array che separano l'elemento cui punta p dall'elemento cui punta q) e supponendo che ogni elemento dell'array risulti memorizzato in 4 byte, la differenza tra l'indirizzo contenuto in p e l'indirizzo contenuto in q darebbe 12. Un puntatore è una variabile , sulla quale possiamo eseguire le più svariate operazioni (come l’assegnamento).

Un array non è una variabile convenzionale (è un contenitore di variabili) ed alcune operazioni da array a puntatore potrebbero non essere permesse.

Comunque tra array e puntatori ci sono sostanziali differenze:

Rischi di errore con array e puntatori

Abbiamo già specificato che il passaggio di un array ad un sottoprogramma avviene sempre per indirizzo , perciò nella chiamata al sottoprogramma non specificherò alcun operatore oltre al nome dell'array. Tuttavia non bisogna confondere il passaggio di tutto l'array con il passaggio di una singola cella dell'array! Se devo passare il contenuto di una cella, mi comporterò come con una variabile del tipo dell'array, quindi dovrò specificare l'operatore '&' poiché devo passarne l'indirizzo per poterla modificare; perciò se ho un array di interi e devo passare la cella i-ma ad un sottoprogramma la sintassi corretta à la seguente: nomeFunzione(&array[i]); Allo stesso modo all'interno del sottoprogramma dovrò dichiarare delle variabili di tipo puntatore che puntino all'indirizzo del parametro attuale per poter effettuare modifiche permanenti. Questo ragionamento è valido anche per le stringhe.

Puntatori

venerdì 13 dicembre 2013 18: