Tipi e Valori Moreno Marzolla Dipartimento di Informatica—Scienza e Ingegneria (DISI) Università di Bologna http://www.moreno.marzolla.name/
Linguaggio C - Tipi e Valori Copyright © Mirko Viroli http://mirkoviroli.apice.unibo.it/ Copyright © 2008, Stefano Mizzaro http://users.dimi.uniud.it/~stefano.mizzaro/dida/Prog0708/ Copyright © 2016, 2017 Moreno Marzolla http://www.moreno.marzolla.name/teaching/FINFA/ This work is licensed under the Creative Commons Attribution-Non Commercial 2.0 (CC BY-NC 2.0) License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/2.0/ or send a letter to Creative Commons, 543 Howard Street, 5th Floor, San Francisco, California, 94105, USA. Linguaggio C - Tipi e Valori
Linguaggio C - Tipi e Valori Ringraziamenti prof. Mirko Viroli, Università di Bologna http://mirkoviroli.apice.unibo.it/ prof. Stefano Mizzaro, Università di Udine http://users.dimi.uniud.it/~stefano.mizzaro/ Linguaggio C - Tipi e Valori
Linguaggio C - Tipi e Valori Identificatori “Nomi” di alcune parti di programma Ci sono varie parti che possono/devono avere un nome: Variabili (base, altezza, contatore, …) Costanti (“variabili il cui valore non può cambiare”) Funzioni (main, altri “pezzi di programma con un nome”) … Linguaggio C - Tipi e Valori
Regole per gli identificatori E' vietato usare parole riservate Cioè identificatori predefiniti che hanno un particolare significato per il compilatore C Es: niente variabili chiamate int, float, for, while, ... Il carattere iniziale deve essere uno fra: A … Z, a … z, _ I caratteri seguenti devono essere scelti fra: A … Z, a … z, _ , 0 … 9 Lunghezza massima 31 caratteri (ANSI C) oppure 63 caratteri (C99) Maiuscole diverse dalle minuscole area e Area sono due identificatori diversi Linguaggio C - Tipi e Valori
Esempi di identificatori Validi AreaRettangolo area_rettangolo A A1 a1 _x (meglio evitare...) Non validi Area Rettangolo Area-Rettangolo Area:Rettangolo 1a Area$ int Può essere domanda d’esame… Il compilatore ci aiuta Se tentiamo di usare un identificatore non valido, segnala un errore in fase di compilazione Linguaggio C - Tipi e Valori
Variabili e costanti Una variabile può essere definita come “un nome a cui è associato un valore” Una variabile può assumere valori diversi durante l'esecuzione del programma, una costante no. /* area-cerchio.c - calcola l'area di un cerchio */ #include <stdio.h> int main( ) { const double PI_GRECO = 3.14; double raggio; double area; raggio = 10.0; area = raggio * raggio * PI_GRECO; printf("%f\n", area); return 0; } PI_GRECO è una costante raggio e area sono variabili Linguaggio C - Tipi e Valori
Linguaggio C - Tipi e Valori Variabili e costanti Se provo ad assegnare un nuovo valore ad una costante, il compilatore segnala un errore /* Calcola l'area di un cerchio */ #include <stdio.h> int main( ) { const double PI_GRECO; double raggio; double area; PI_GRECO = 3.14; raggio = 10.0; area = raggio * raggio * PI_GRECO; printf("%f\n", area); return 0; } area-cerchio.c: In function ‘main’: area-cerchio.c:10:5: error: assignment of read-only variable ‘PI_GRECO’ PI_GRECO = 3.14; ^ Linguaggio C - Tipi e Valori
Inizializzazione delle variabili Quando si dichiara una variabile o una costante, è possibile specificare il suo valore iniziale Se non viene specificato, il valore iniziale è indefinito int inizio, fine; /* valori iniziali indefiniti */ int mesi = 12; /* valore iniziale 12 */ /* radice ha valore iniziale indefinito, tasso ha valore iniziale 12.3 */ double radice, tasso = 12.3; Linguaggio C - Tipi e Valori
Linguaggio C - Tipi e Valori Attenzione Le variabili non inizializzate possono avere valore iniziale arbitrario Accedere al valore di una variabile non inizializzata è un errore grave, sebbene il compilatore generi comunque un programma eseguibile /* undefined.c: non c'e' modo di prevedere cosa stampa questo programma (compilando con -Wall il compilatore segnala un warning) */ #include <stdio.h> int main( ) { int a; printf("a=%d\n", a); return 0; } Il compilatore non genera alcun errore né warning quando si compila questo programma. Genera un warning solo se si usa l'opzione -Wall > gcc -Wall undefined.c -o undefined undefined.c: In function ‘main’: undefined.c:17:15: warning: ‘a’ is used uninitialized in this function [-Wuninitialized] printf("a=%d\n", a); ^ Linguaggio C - Tipi e Valori
Definizione di variabili Una variabile è “visibile” (quindi utilizzabile) solo dopo che è stata dichiarata Vedremo... ANSI C consente dichiarazioni solo all'inizio di un blocco Cioè subito dopo { Una variabile è visibile solo all'interno del blocco in cui è stata dichiarata #include <stdio.h> int main( ) { int a = 3; printf(“Hello, world!\n”); printf(“a=%d\n”, a); if ( a>0 ) { int b = 10; printf("b=%d\n", b); } else { int b = 17; } return 0; Linguaggio C - Tipi e Valori
Digressione: ANSI C vs C99 Esistono costrutti di programmazione che sono validi in C99, ma non in ANSI C Se volete che il vostro programma sia conforme con le specifiche di ANSI C compilate con gcc -ansi -pedantic … Se volete che il vostro programma sia conforme con le specifiche di C99 compilate con gcc -std=c99 -pedantic ... Quale usare? Di default, gcc riconosce tutti i costrutti ANSI C, più alcuni costrutti di C99 Quindi non serve fare nulla in particolare: tutto quello che viene accettato da gcc per noi sarà ok Linguaggio C - Tipi e Valori
Linguaggio C - Tipi e Valori In realtà una variabile è “un nome con associato un valore di un certo tipo” Se una variabile contiene valori interi, non può assumere un valore reale Il tipo di una variabile è deciso dal programmatore con una dichiarazione E' necessario dichiarare le variabili prima di poterle usare Linguaggio C - Tipi e Valori
Linguaggio C - Tipi e Valori I tipi primitivi del C Ci sono solo quattro tipi primitivi in C char Un singolo byte (8 bit), in grado di contenere il codice ASCII di un carattere int Un intero (positivo o negativo) di lunghezza fissata, che normalmente riflette la lunghezza "naturale" degli interi sulla macchina (32 o 64 bit) float Un valore in virgola mobile a singola precisione double Un valore in virgola mobile a doppia precisione Linguaggio C - Tipi e Valori
Linguaggio C - Tipi e Valori Short, Long, Unsigned Ad ognuno dei 4 tipi può essere preposto short o long Però viene quasi sempre usato solo col tipo int Es: short int, long int Consente di avere versioni dei tipi codificate con più o meno bit A char e int si può preporre unsigned, che dà una versione con valori solo positivi Ad esempio unsigned char assume valore in 0..255 Il fatto che il tipo char sia di default signed o unsigned è dipendente dall'architettura (!) E' possibile usare le abbreviazioni seguenti: short al posto di short int long al posto di long int unsigned al posto di unsigned int Linguaggio C - Tipi e Valori
Linguaggio C - Tipi e Valori Su una tipica macchina a 32 bit: Type Keyword Bytes Valori rappresentabili character char 1 -128...127 unsigned character unsigned char 1 0...255 integer int 4 -2,147,483,648...2,147,438,647 unsigned integer unsigned int 4 0...4,294,967,295 short integer short 2 -32768...32767 unsigned short integer unsigned short 2 0...65535 long integer long 4 -2,147,483,648...2,147,438,647 unsigned long integer unsigned long 4 0...4,294,967,295 single-precision float 4 1.2E-38...3.4E38 double-precision double 8 2.2E-308...1.8E308 Linguaggio C - Tipi e Valori
Linguaggio C - Tipi e Valori I tipi primitivi del C La specifica del linguaggio non indica quanti bit bisogna usare per rappresentare valori di ciascun tipo E' possibile scoprire cosa fa il vostro compilatore usando l'operatore sizeof(T) Restituisce il numero di byte necessari per rappresentare una variabile di tipo T Il linguaggio C garantisce che 1 = sizeof(char) ≤ sizeof(int) ≤ sizeof(float) ≤ sizeof(double) Linguaggio C - Tipi e Valori
Uso di sizeof() /* size.c */ #include <stdio.h> int main( void ) { printf("Size of char is %lu\n", sizeof(char)); printf("Size of short int is %lu\n", sizeof(short int)); printf("Size of int is %lu\n", sizeof(int)); printf("Size of long int is %lu\n", sizeof(long int)); printf("Size of float is %lu\n", sizeof(float)); printf("Size of double is %lu\n", sizeof(double)); printf("Size of long is %lu\n", sizeof(long)); printf("Size of short is %lu\n", sizeof(short)); return 0; } Purtroppo sizeof() restituisce un valore di tipo size_t; se come argomento di printf() usiamo %d il compilatore segnalerà dei warning (warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat=] ). Il modo più portabile per evitare questo warning è utilizzare il formato %lu %lu indica che l'argomento di printf è di tipo “unsigned long” Linguaggio C - Tipi e Valori
Linguaggio C - Tipi e Valori Uso di sizeof() output Size of char is 1 Size of short int is 2 Size of int is 4 Size of long int is 8 Size of float is 4 Size of double is 8 Size of long is 8 Size of short is 2 Linguaggio C - Tipi e Valori
Linguaggio C - Tipi e Valori Valori costanti Valori costanti di tipo int 10, -3, 6531 (decimali) 0x0, 0xf0f, 0xAB09 (esadecimali, iniziano con 0x) 07, 0132, 021 (ottali, iniziano con 0) Attenzione: 32 ≠ 032 (il primo è in base 10, il secondo in base 8!) Valori costanti unsigned / long 10u (unsigned int), -37l (long), 1732ul (unsigned long) Valori costanti di tipo double 1.0, -8.23, 1.0e5 (=1.0 ´ 105), -19.3E-2 (-19.3 ´ 10-2) Valori costanti di tipo float 1.0f, -8.23f, 1.0e-4f, -19.3E-2f (notare la 'f' finale) Valori costanti di tipo char (racchiusi tra singoli apici) 'a', 'Z', ' ' (spazio), '\n' (a capo), '0', '_' Valori costanti di tipo stringa (sequenze di caratteri racchiusi tra virgolette) “Hello, world!\n”, “” Linguaggio C - Tipi e Valori
Linguaggio C - Tipi e Valori Quindi 10 ha tipo int 010 ha tipo int e rappresenta il valore decimale 8 0x10 ha tipo int e rappresenta il valore decimale 16 10.0 ha tipo double 10.0f ha tipo float 'a' ha tipo char Linguaggio C - Tipi e Valori
Linguaggio C - Tipi e Valori <stdint.h> Lo standard C99 prevede un header file stdint.h che definisce tipi interi le cui rappresentazioni usano un numero di bit prefissato Signed: int8_t, int16_t, int32_t, int64_t Unsigned: uint8_t, uint16_t, uint32_t, uint64_t Per usare questi tipi occorre includere stdint.h aggiungendo all'inizio del proprio programma la direttiva #include <stdint.h> Linguaggio C - Tipi e Valori
Linguaggio C - Tipi e Valori Funzione printf E' usata per stampare a video Accetta 1 o più argomenti (parametri) Il primo è una stringa (letterale, cioè racchiusa tra “...”) La stringa contiene caratteri, che vengono stampati tali e quali, e altri caratteri di controllo Linguaggio C - Tipi e Valori
printf : caratteri di controllo I seguenti caratteri di controllo stampano un valore di un certo tipo, passato come ulteriore parametro: %d stampa un valore di tipo int %ld stampa un valore di tipo long int %u stampa un valore di tipo unsigned int %lu stampa un valore di tipo long unsigned int %c stampa un carattere di tipo char %s stampa un valore di tipo stringa (vedremo...) %f stampa un valore di tipo float o double Casi particolari: Usare %d per stampare la rappresentazione numerica di un char o unsigned char Linguaggio C - Tipi e Valori
Escape characters in printf Nella stringa si possono inserire caratteri speciali (escape characters) \n per andare a capo \r per tornare a inizio riga \t per stampare una tabulazione \\ per stampare il carattere \ %% per stampare il carattere % \" per stampare il carattere virgolette " Linguaggio C - Tipi e Valori
Linguaggio C - Tipi e Valori Uso del tipo char 'A', 'a', 65 (codice ASCII di 'a') #include <stdio.h> int main( void ) { char c1 = 'a', c2 = 'A', c3 = 65; printf("%c %c %c %c\n", c1, c1+1, c2, c3); return 0; } a b A A Linguaggio C - Tipi e Valori
Linguaggio C - Tipi e Valori /* test-printf.c */ #include <stdio.h> int main( void ) { char a = 'w'; int b = -12; double c = 3.14; float d = 2.54; /* nota: conversione double → float */ unsigned int e = 133; /* nota: conversione int → unsigned int */ printf("a e b valgono \"%c\" e \"%d\"\n", a, b); printf("c vale \"%f\"\n", c); printf("d vale \"%f\"\n", d); printf("e vale \"%u\"\n", e); return 0; } > gcc test-printf.c -o test-printf > ./test-printf a e b valgono "w" e "-12" c vale "3.140000" d vale "2.540000" e vale "133" Linguaggio C - Tipi e Valori
scanf : caratteri di controllo Gli stessi caratteri di controllo si possono usare con scanf() per leggere un valore da tastiera e assegnarlo ad una variabile di un certo tipo scanf("%d",&x) legge un int e lo assegna a x scanf("%ld",&x)legge un long int e lo assegna a x scanf("%u",&x) legge un unsigned int e lo assegna a x scanf("%lu",&x)legge un long unsigned int e lo assegna a x scanf("%f",&x) legge un float e lo assegna a x scanf("%lf",&x)legge un double e lo assegna a x Attenzione: il valore di una variabile di tipo double si stampa con "%f" ma si legge con "%lf" !! Linguaggio C - Tipi e Valori
Linguaggio C - Tipi e Valori scanf: attenzione... Leggere un valore numerico da assegnare ad una variabile di tipo char o unsigned char è problematico Suggerisco di procedere in due passi: Leggere un intero con %d e assegnarlo ad una variabile di tipo int Assegnare il valore letto alla variabile desiderata di tipo char/unsigned char (è una operazione ammessa, vedremo nella prossima lezione) int xint; char xchar; scanf("%d", &xint); xchar = xint; Linguaggio C - Tipi e Valori
Linguaggio C - Tipi e Valori Esempio /* test-scanf.c */ #include <stdio.h> int main( void ) { int b; double c; float d; unsigned int e; printf("Digita un int\n"); scanf("%d", &b); printf("Hai digitato: %d\n", b); printf("Digita un double\n"); scanf("%lf", &c); printf("Hai digitato: %f\n", c); printf("Digita un float\n"); scanf("%f", &d); printf("Hai digitato: %f\n", d); printf("Digita un unsigned int\n"); scanf("%ud", &e); printf("Hai digitato: %ud\n", e); return 0; } Linguaggio C - Tipi e Valori
Linguaggio C - Tipi e Valori I booleani? In C non esiste un tipo predefinito per indicare valori booleani (true/false) Si usano al loro posto gli interi 0 vuol dire falso tutti gli altri valori significano vero (si consiglia di usare 1 per indicare vero) Quindi: l'espressione (20 > 10) ha tipo int e valore 1 l'espressione (10 > 20) ha tipo int e valore 0 Linguaggio C - Tipi e Valori
Linguaggio C - Tipi e Valori Tipi in virgola mobile Numerici in virgola mobile (numeri razionali) codifica IEEE 754 Tipi: float: 32-bit double: 64-bit Rappresentazione decimale standard -45.31458 (il “.” è necessario!) con esponente -3.141E-12 oppure -3.141e-12 (sarebbe -3.141´10 -12 ) Di default il tipo assegnato è double per specificare un float si usa la f o F finale: 1.56f Linguaggio C - Tipi e Valori
Attenzione alla precisione Errori di precisione 1e9 + 1e-9 si valuta in 1e9 (3.5/51)*51 si valuta in 3.5000000000000004 I numeri in virgola mobile codificano base ed esponente double: 53 bit per base e 11 per esponente Non si possono codificano “infinite” cifre dopo la virgola, quindi si può commettere un errore nel rappresentare un numero In genere non comporta problemi ma a volte sì 1e9 + 1e-9 == 1e9 → si valuta in “true” Linguaggio C - Tipi e Valori
Riassumendo: dichiarazioni di variabili Forma generale: Tipo NomeVariabile1 = Expr1, … NomeVariabilen = Exprn; Esempi Dichiarazioni Dichiarazioni con inizializzazione esplicita double base, altezza; double area; int penultimo, ultimo, contatore; Esempi alla lavagna double base = 4.4, altezza = 3.2 double area = (base * altezza) / 2; Linguaggio C - Tipi e Valori