Struttura Di Un Programma C
Struttura Di Un Programma C
Struttura di un Programma C
24
----------------------------------------------------------------
Identificatori
• Sono identificatori per il C che possono essere usati per indicare
variabili, funzioni, etichette e dati di tipo definito dall'utente.
Ogni identificatore, usato sia per dentificare variabili sia per indicare
funzioni, deve essere diverso dalle parole riservate utilizzate per il
linguaggio C, e deve essere diverso anche dai nomi di variabili o funzioni
delle librerie utilizzate durante la fase di linking.
25
----------------------------------------------------------------
Tipi di Dati Semplici
Il C mette a disposizione i seguenti dati di tipo semplice:
Tipo Size (byte) Valore Valore Equivalente
minimo Massimo in Pascal
signed char 1 -128 +127 char
unsigned char 1 0 255 ---
short int 2 -32768 +32767 integer
unsigned short int 2 0 65535 ---
long int 4 -231 +231-1 longint
unsigned long int 4 0 +232-1 ---
float 4 -3.2 x 10±38 +3.2 x 10±38 real
double 8 -1.7 x 10±308 +1.7 x 10±308 extended
void 0 non definito non definito ---
Osservazioni importante:
• Sui sistemi UNIX tutte le variabili dichiarate "int" sono considerate long
int", mentre "short int" deve essere dichiarato esplicitamente.
• In alcune architetture, inoltre, il dato di tipo int è costituito da un numero
maggiore di byte.
• E' importante notare che in C non esiste un tipo di variabile booleano.
• Come variabili di tipo booleano si possono utilizzare variabili "char",
"int", "long int" sia signed che unsigned.
• Ciascuno di questi dati, quando viene valutato dal punto di vista booleano,
è valutato FALSO quando assume valore 0 (ZERO), se invece assume
un valore diverso da zero è valuato come VERO.
Per esempio, la seguente istruzione condizionale if(-1) i=1;
esegue l'assegnamento perchè il valore -1 è considerato VERO.
Il tipo void rappresenta un tipo di dato indefinito, e ha due funzioni: serve ad
indicare che una funzione non restituisce nessun valore, e serve per definire
un puntatore che punta ad un dato generico.
26
----------------------------------------------------------------
Variabili
Tutte le variabili devono essere dichiarate prima di essere usate.
La dichiarazione delle variabili è così fatta:
Tipo ElencoVariabili;
27
----------------------------------------------------------------
Variabili Locali
Definiamo Blocco di Istruzioni una sequenza di istruzioni C racchiusa tra
una parentesi graffa aperta ed una parentesi graffa chiusa.
Il corpo di una funzione (il codice C che implementa una funzione) è un
caso particolare di Blocco.
Esempi di Blocchi:
Ovunque, usando il
Corpo di Funzione Interno di ciclo for Trucco aperta-chiusa {}
28
----------------------------------------------------------------
Variabili come Parametri Formali
Sono le variabili che definiscono, nell'implementazione di una funzione, i
parametri passati come argomenti alla funzione.
Sono esattamente equivalenti ai parametri formali delle funzioni o procedure
del Pascal.
Per default i dati di tipo semplice sono passati per valore, come in Pascal.
Invece i dati di tipo matrice sono passati per puntatore (la modalità var del
pascal).
C Pascal
29
----------------------------------------------------------------
Variabili Globali e Specificatore extern
Le variabili Globali sono quelle variabili che sono dichiarate fuori da tutte
le funzioni, in una posizione qualsiasi del file.
Una tale variabile allora verrà detta globale, perchè
• potrà essere acceduta da tutte le funzioni che stanno nello stesso file ma
sempre sotto alla dichiarazione della variabile stessa,
• potrà essere acceduta da tutte le funzioni che stanno in altri file in cui
esiste una dichiarazione extern per la stessa variabile, ma sempre sotto
alla dichiarazione extern della variabile stessa,
• e avrà durata pari alla durata in esecuzione del programma.
Per default, una variabile globale NomeVariabile è visibile da tutti i moduli
in cui esiste una dichiarazione di variabile extern di NomeVariabile, ovvero
una dichiarazione siffatta:
extern tipo NomeVariabile;
che è la solita dichiarazione di variabile preceduta però dalla parola extern.
Una tale dichiarazione dice al compilatore che:
1. nel modulo in cui la dichiarazione extern è presente, la variabile
NomeVariabile non esiste,
2. ma esiste in qualche altro modulo,
3. e che il modulo con la dichiarazione extern è autorizzato ad usare la
variabile,
4. e quindi il compilatore non si deve preoccupare se non la trova in questo
file,
5. perchè la variabile esiste da qualche altra parte.
6. Sarà il Linker a cercare in tutti i moduli fino a trovare il modulo in cui
esiste la dichiarazione senza extern per la variabile NomeVariabile.
La variabile NomeVariabile viene fisicamente collocata solo nel modulo
in cui compare la dichiarazione senza extern, (che deve essere uno solo
altrimenti il Linker non sa cosa scegliere) e precisamente nel punto in cui
compare la dichiarazione. Nei moduli con la dichiarazione extern invece
rimane solo un riferimento per il linker.
30
----------------------------------------------------------------
Protezione dagli Accessi esterni al modulo:
Variabili Globali e specificatore Static
Se vogliamo che una certa variabile globale NomeVariabile, collocata in un
certo file, non sia accedibile da nessun altro modulo, dobbiamo modificare
la sua dichiarazione in quel modulo, facendola precedere dalla keyword
static ottenendo una dichiarazione di questo tipo.
static tipo NomeVariabile;
In tal modo, quella variabile potrà ancora essere acceduta dalle funzioni nel
suo modulo, ma da nessun altro modulo.
31
Esempio, Problemi con variabili globali, all'interno
dello stesso file in cui le variabili globali sono definite
#include <stdio.h>
int main(void)
{
int i=34;
double g=13;
void funzione1(void)
{
printf("g = %f \n", g ); /* stampa g, cioè 13, corretto */
printf("i = %d \n", i ); /* NON VEDE i, ERRORE */
}
32
Esempio, Problemi tipici in programmi con più moduli.
Il nostro programma è costituito da due moduli, var.c e main.c.
• main.c contiene il main del programma, ed alcune funzioni, tra cui la
funzione f , che accetta come parametro formale un intero e lo stampa.
• var.c contiene alcune variabili intere, alcune (A)globali, altre (C) globali
ma statiche e quindi visibili solo dentro il modulo var.c.
• Non esiste una variabile B da nessuna parte.
/* file var.c */ #include <stdio.h> /* file main.c */
extern int A;
int A=1; extern int C;
static int C; void f(int c){ printf("c=%d\n",c); } /*stampa intero */
void main(void)
{
f(A); /* corretto */
f(B); /* error C2065: 'B' : undeclared identifier*/
f(C); /* error LNK2001:unresolved external symbol _C*/
}
Il modulo main.c contiene due errori, perchè:
1) con l'istruzione f(C) main tenta di accedere alla variabile C che non può
vedere perchè è protetta dallo specificatore static che la rende visibile solo
dentro var.c.
• Il compilatore non si accorge dell'errore perchè main.c ha una
dichiarazione extern per C, e il compilatore si fida e fa finta che C esista e
sia accedibile in un qualche altro modulo.
• Il linker invece, che deve far tornare i conti, non riesce a rintracciare una
variabile C accedibile, e segnala l'errore indicando un "error LNK2001:
unresolved external symbol" perche non trova C.
2) con l'istruzione f(B) main tenta di accedere alla variabile B che non è
definita nel modulo main.c, nemmeno da una dichiarazione extern.
• il compilatore si accorge dell'errore e lo segnala con il messaggio "error
C2065: 'B' : undeclared identifier".
33
----------------------------------------------------------------
Protezione dagli Accessi esterni alla funzione
per variabili che debbono mantenere un valore
tra una chiamata alla funzione e la successiva ad una funzione.
Lo specificatore static, appliccato ad una variable locale ordina al
compilatore di collocare la variabile non più nello stack all'atto della
chiamata alla funzione, ma in una locazione di memoria permanente (per
tutta la durata del programma), come se fosse una varabile locale.
Ma a differenza della variabile globale, la variabile locale static sarà visibile
solo all'interno del blocco in cui è stata dichiarata.
L'effetto è che la variabile locale static:
• viene inizializzata una sola volta, la prima volta che la funzione viene
chiamata.
• mantiene il valore assunto anche dopo che il controllo è uscito dalla
funzione, e fino a che non viene di nuovo chiamata la stessa funzione.
vediamo un esempio di utilizzo, per contare il numero delle volte che una
data funzione viene eseguita.
34
----------------------------------------------------------------------------------------------------------------------
i = 0; corretta
i = func( 3.8 ); corretta
j=i; corretta
func( 3.8 ) = 100; NON AMMESSA, errore in compilazione
35
----------------------------------------------------------------------------------------------------------------------
N.B.
In entrambi i casi il compilatore si accorge che c'e' una perdita di dati nel
passaggio da double a int e avverte il programmatore con un warning di
questo tipo:
warning: '=' : conversion from 'double ' to 'int ', possible loss of data
36
----------------------------------------------------------------------------------------------------------------------
short int i
char ch
37