Informatica 2 – modulo C · 2011. 3. 1. · Tipi di dato • In C esistono due categorie di tipi:...
Transcript of Informatica 2 – modulo C · 2011. 3. 1. · Tipi di dato • In C esistono due categorie di tipi:...
Informatica 2 – modulo CMassimo Callisto De Donato
www.cs.unicam.it/massimo.callisto
LEZIONE 3 – TIPI DI DATO
Università degli studi di CamerinoScuola di scienze e tecnologia - Sezione Informatica
Tipi di dato
• In C esistono due categorie di tipi: primitivi e derivati.
• I tipi primitivi (o fondamentali):
void enum char int float double
• I tipi derivati (o composti):
array strutture unioni
• I secondi sono costruiti a partire dai primi e vengono usati per raggruppare variabili logicamente correlate.
• Il tipo void è stato introdotto dallo standard ANSI non è un tipo ma rappresenta il valore vuoto. As esempio si usa un funzioni che non restituiscono valori.
Sintassi delle dichiarazioni• Qualunque identificatore (variabile e/o funzione) deve essere dichiarato prima di poter essere
utilizzato!
• Dichiarare una variabile significa specificare a quale tipo appartiene. Questo significa indirettamente dire al compilatore:
– Quanta memoria deve essere riservata
– Quali sono le operazioni ammesse su di essa.
• Sintassi di una dichiarazione:
tipo variabile; //oppure elenco variabili separate da virgole;
• Esempi:– char letter;
– int number, sum;
– float f, media;
• Sempre bene inizializzare una variabile in fase di dichiarazione. Questo evita che ci sino valori indefiniti potenzialmente dannosi:– char letter = 'A';
– int number = 0, sum;
– float f = 2.178;
• Ricordate i vincoli:
Max 32 caratteri per il nome;
Distinzione MAIUSCOLE/muniscole
Caratteri alfanumerici + il simbili “_”
La prima deve essere una lettera o “_”
Tipi di dato: char• Rappresenta caratteri alfanumerici, simboli di punteggiatura, spazi, etc.
• I caratteri char sono tra apici. Es: 'A', '0', '#'. In particolare:– 'A' (è un char) è diverso da "A" (è un vettore formato da 'A' e ' \0 ‘)
• I caratteri sono codificati (memorizzati) come sequenze di cifre binarie.
• In C si adotta il codice ASCII:– 8 bits (1 byte) per codificare un carattere (originale erano 7)
– max 255 caratteri (originale 127)
• Quindi, ogni carattere viene identificato univocamente con una sequenza di bit. Ad esempio:– Il carattere 'A' viene codificato mediante la sequenza binaria 01000001
– Corrisponde all’intero positivo 65
• Spesso manipoliamo i caratteri dal punto di vista numerico visto che sono supportate le tipiche operazioni su interi: addizione, sottrazione, uguaglianze, …
Tipi di dato: char
Tipi di dato: char#include <stdio.h>
#include <stdlib.h>
int main()
{
char c;
printf("Inserisci un carattere: ");
c = getchar();
printf("Hai inserito una '%c' che ha valore %d\n", c, c);
system("PAUSE");
return 0;
}
Tipi di dato: char/* Differenza di input */
#include <stdio.h>
#include <stdlib.h>
int main()
{
char c1;
int c2;
printf("Inserisci un carattere: ");
c1 = getchar();
printf("Stesso catrattere da scanf: ");
scanf("%d", &c2);
printf("Primo input '%d'\nSecondo input '%d'\n", c1, c2);
system("PAUSE");
return 0;
}
Tipi primitivi: i tipi int, float e double
• Il tipo int rappresenta interi la cui dimensione è tipicamente a 32 bit (4 byte): max 4294967295
• Il tipo float rappresenta numeri reali in virgola mobile con precisione singola. Occupa tipicamente 4 byte.
• Il tipo double rappresenta numeri reali in virgola mobile con precisione doppia. Occupa tipicamente 8 byte.
• Le dimensioni effettive dei tipi primitivi dipendono in realtà dall’architettura della macchina che stiamo usando. In generale vale questo:
|char| <= |int|
|float| <= |double|
Tipi primitivi: i tipi int, float e double
• Ulteriori specifiche con short e long (quantificatori di dimensione),
signed e unsigned (quantificatori aritmetici).
• short e long modificano la dimensione di default della memoria
associata ad una variabile:
– short int è un int con dimensione minore o uguale a quella di int
– long int è un int maggiore o al più uguale a quella di int
• Dipende però dalla macchina ma vale:
|short int| <= |int| <= |long int|
|double| <= |long double|
Tipi primitivi: i tipi int, float e double
• Ulteriori specifiche con short e long (quantificatori di dimensione),
signed e unsigned (quantificatori aritmetici).
• Gli specificatori signed (int o char) e unsigned (int o char) si
applicano ai tipi char e int e fanno esplicitamente riferimento all’aritmetica
senza segno:
– I valori numerici possono essere solo positivi
– Es: range di int è +/- 2147483647, range di unsigned int è + 4294967295
• signed definisce che una variabile ha il segno ma ridondante visto che è
di default.
• Spesso si usano delle abbreviazioni:
short short int
unsigned unsigned int
Unsigned short unsigned short int
unsigned long unsigned long int
Costanti
• Esistono quattro principali categorie di costanti– costanti carattere: 'A', '0', '#'
– le costanti intere:• base decimali: 0, 89
• base ottale (in base 8) precedute da 0: 012, 077
– 12(base 8) = (1 * 8^1) + (2 * 8^0) = 8 + 2 = 10
– 77(base 8) = (7 * 8^1) + (7 * 8^0) = 56 + 7 = 63
• base esadecimale (in base 16) precedute da 0x oppure 0X: 0xAA, 0X77
– costanti floating point: 23.56, -45.897
– costanti stringa: "stringa", "pippo”
Costanti• Esistono quattro principali categorie di costanti
– costanti carattere: 'A', '0', '#'
– le costanti intere:• base decimali: 0, 89
• base ottale (in base 8) precedute da 0: 012, 077
– 12(base 8) = (1 * 8^1) + (2 * 8^0) = 8 + 2 = 10
– 77(base 8) = (7 * 8^1) + (7 * 8^0) = 56 + 7 = 63
• base esadecimale (in base 16) precedute da 0x oppure 0X: 0xAA, 0X77
– costanti floating point: 23.56, -45.897
– costanti stringa: "stringa", "pippo”
• Suffissi:
– Se int di default è int o long. Possiamo specificarlo manualmente con l o L
– Se è un float allora è un float o double. Possiamo indicarlo con f o Fper un float oppure l o L per un double
Costanti
• Esempi:
#define BASE 10 //intero
#define BASE_8 012 //intero ma in base ottale
#define BASE_16 0xA //intero ma in base esadecimale
#define BASE_L 10L // INTERO LONG
#define AREA 123.4 // FLOAT
#define STR “pippo” // stringa
Enum
• Si usano quando si vuole specificare un insieme preciso di valori che una variabile può assumere. Es:
enum color {red, blue, green, yellow};
enum intensity {bright, medium, dark};
• Sintassi generica:
enum nome_tipo {lista_costanti};
• Ai nomi delle costanti viene associato un valore intero di default basato sulla posizione nella lista:
– la prima costante assume valore 0
– alla seconda uno, etc
• Il valore può essere modificato esplicitamente (es.: enum succ
{success = 1, failure = 0})
Enum#include <stdio.h>
int main()
{
enum days {Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday};
enum days TheDay;
int j = 0;
printf("Please enter the day of the week (0 to 6)\n");
scanf("%d",&j);
TheDay = j;
if(TheDay == Sunday || TheDay == Saturday){
printf("Weekend\n");
}else{
printf("Work\n");
}
system("PAUSE");
return 0;
}
Operatori
• Abbiamo tre tipi di operatori: assegnamento, aritmetici, relazionali.
• Operatore di assegnamento: nome_variabile = espressione
• Espressione può essere semplice o complessa a piacere.
• Il valore risultante dalla valutazione di espressione (parte destra) viene
assegnato alla variabile di nome nome variabile (parte sinistra): variabile
espressione
• L’operatore di assegnamento può comparire all’interno di una qualsiasi
espressione valida. Ad esempio : y = 2 + (x = 7 * 3);
• E’ possibile effettuare degli assegnamenti multipli a patto che le variabili
siano dello stesso tipo: int x = y = 5
• Questo no: int z, f= 10.5, k = „c‟;
Operatori aritmeici
• La maggior parte degli operatori aritmetici può essere applicato sia ad operandi interi che ad operandi reali.
• Se l’operatore / viene applicato ad interi, l’eventuale resto della divisione viene troncato: 5 / 2 = 2 mentre 5.0/2 = 2.5
• a % b restituisce il resto della divisione intera tra a e b e può essere utilizzato solamente con operandi interi. Es: 6.98 % 3 produce un errore di compilazione
Operatori aritmetici
• L’ordine di valutazione degli operatori aritmetici stabilisce quali operatori devono essere valutati per primi. Esempi:– 15 + 4 * 13 viene valutata come 15 + (4 * 13)
– 16 / 4 + 3 come (16 / 4) + 3
– a++ - 5 * --b come (a++) - (5 * (--b)) [Se a = 5 e b = 6, il risultato è?]
• A parità di precedenza, l'associazione è a sinistra (si scorre l’espressione da sinistra a destra). Esempi: – 15 - 4 - 13 viene valutata come (15 - 4) - 13 = -2
– non come 15 - (4 - 13) = 15 - (-9) = 15 + 9 = 24
• Le priorità e l'associatività possono essere modificati con l’uso di parentesi ()
Operatori aritmetici unari
• L’operatore di incremento (decremento) unario ++ aggiunge (sottrae) una unità al proprio operando– ++x; ha lo stesso effetto di x = x + 1;
– --x; ha lo stesso effetto di x = x - 1;
• Possono precedere oppure seguire la variabile: – ++x (notazione prefissa)
– x++ (notazione postfissa);
• La differenza è nel valore restituito:– notazione prefissa: viene prima effettuato l’incremento (decremento) e poi valutata
espressione
– notazione postfissa: viene prima valutata l’espressione e poi effettuato l’incremento (decremento)
• Ad esempio, se n è una variabile intera di valore 5– x = ++n; assegna a x il valore 6
– x = n++; assegna a x il valore 5
• a++ - 5 * --b come (a++) - (5 * (--b)) [Se a = 5 e b = 6, il risultato è?]
Operatori aritmetici abbreviazioni
• Nel caso in cui una variabile debba essere incrementata o decrementata di un valore diverso da 1 si possono usare forme compatte += e -=
• Ad esempio x += 9; ha lo stesso effetto di x = x + 9;
• Sintassi generica: operatore= dove operatore = {+, -, *, /, %}
– a += 5 a = a + 5
– a -= b
– a = a – b
– a *= b + 4
– a = a * (b + 4)
• Hanno la stessa priorità dell’assegnamento semplice. Esempio:
• a = 4; a -= 3 * 2 + 11 4 - ((3 * 2) + 11) = 4 - 17 = -13
Operatori relazionali e logici
• Gli operatori relazionali stabiliscono relazioni tra valori.
• Gli operatori logici permettono di connettere pi`u operatori relazionali
Operatori relazionali e logici
• Tavola di verità degli operatori logici
• In C non esiste un tipo booleano (true o false).
• Piuttosto operatori relazionali (logici) restituiscono valori numerici:– 0 per falso
– Un qualsiasi valore diverso (tipicamente 1) per vero
• Il risultato di un’espressione (logica o relazionale) può essere assegnato a delle variabili intere. Esempio: x = 5 > 7, x = (9 <= 10) && 1
• Se usassimo enum per rappresentare i booleani?
Priorità degli operatori logici e relazionali:
• L’espressione 10 > 1 == 12 viene valutata come (10 > 1) == 12 e
restituisce 0 (falso)
• L’espressione 1 || 0 && 0 viene valutata come 1 || (0 && 0) e
restituisce 1 (vero)
• L’associazione è a sinistra:
• 13 > 7 >= 6 viene valutata come (13 > 7) >= 6 e restituisce 1 >= 6
0 (falso)
• L’espressione 13 > (7 >= 6) restituisce 13 > 1 cioè 1 (vero)
• Gli operatori relazionali e gli operatori logici AND e OR hanno una
precedenza inferiore rispetto a quelli aritmetici (vengono valutati dopo).
• Gli operatori logici AND e OR hanno una precedenza inferiore rispetto a
quelli relazionali.
10 > 1 + 12 10 > (1 + 12) e ritorna?
(10 > 1) + 12 restituisce „„vero‟‟ + 12 = 1 + 12 = 13
Operatore ?
• Un’espressione condizionale si ottiene usando l’operatore ternario ?
• La sintassi è: expr1 ? expr2 : expr3
– Restituisce expr2 se expr1 è vera;
– Restituisce expr3 altrimenti (expr1 è falsa).
• L’operatore ? ha una priorità maggiore dell’operatore di assegnamento. Esempio: int v = (x == y) ? 39 : 7
y = x < 5 ? 1 : 2;
y = x ? x : 0;
y = ++x ? x : x--;
y = (x + 1) ? x : 0;
Y = (1 && 0) ? (0 || 1) : !1;
Gerarchia finale
Conversione di tipo (casting)
• Nelle operazioni in cui agli operatori si applicano operandi di tipo diverso, il C
esegue una conversione automatica (implicita). Es.: 98.89 + 189 restituisce
287.89.
• Regole: tutti gli operandi di tipo “inferiore” vengono convertiti nell’operando di
tipo “superiore”. Il risultato e di tipo “superiore”
• Negli assegnamenti il valore a destra viene convertito nel tipo a sinistra. Es.: int
y = 24.5 + 2;
• Warning dal compilatore e comunque non andrebbe fatto.
int x = 280;
char ch;
float f = 4.976;
ch = x; // int convertito in char i 24 bitsuperiori di x vengono ignorati
x = f; // float viene convertito in int, x ricevela parte intera di f
f = x; //stesso valore ma in virgola mobile
x = x + f; // quante conversioni vengono effettuate?
Conversione di tipo (casting): esplicito
• Il tipo di un’espressione può essere esplicitamente convertito in un altro tipo per
mezzo di un’operazione detta casting:
• (nome tipo) espressione
• Esempio:
– La funzione di libreria sqrt (calcola la radice quadrata del suo argomento) deve operare su un
argomento di tipo double.
#include <math.h>
double sqrt(double x);
– Se n è un intero, possiamo scrivere sqrt((double) n)
• Nell'esempio di prima x = x + f si poteva scrivere x = x + ((int) f)
• Cosa stampa?
char c = ‘A’;
printf(“%d”, (int;) c)