Sei sulla pagina 1di 6

2

Precedenza e associatività
() [] -> . SD
! ~ ++ –– + – * & (cast ) sizeof SD
* / % SD
Complementi sul C - 2 + - (somma e sottrazione)
<< >>
SD
SD
< <= > >= SD
== != SD
& SD
Ver. 2.4 ^ SD
| SD
&& SD
|| SD
?: SD
= += –= *= /= %= &= ^= |= <<= >>= SD
, SD
© 2010 - Claudio Fornaro - Corso di programmazione in C  SD: da Sinistra a Destra, SD: da Dst. a Sin.

3 4

Esempi Esempi
 *p.x equivale a *(p.x)  int (*f)(long)
 *p->n++ equivale a *((p->n)++) f è un puntatore a funzione con un
 char **q equivale a char *(*q) argomento long e che restituisce un int
q è un puntatore a puntatore a char  int *f(long)
 int mx[5][7] equivale a int (mx[5])[7] f è una funzione con argomento un
mx è vettore di 5 vettori di 7 int long e che restituisce un puntatore a int
 int *vett[5] equivale a int *(vett[5])
vett è un vettore di 5 puntatori a int
 int (*vett)[5]
vett è un puntatore a un vettore di 5 int
5 6

Esempi Esempi
 char (*(*x())[])() void (*signal(int sig,
x è una funzione che restituisce un puntatore void (*handler)(int))
(le () hanno precedenza sull’ *) ad un array di )(int)
puntatori a funzione che restituiscono un char signal è una funzione che ha come parametri
 char (*(*x[3])(double,double))[5]  un int (sig)
x è un array di 3 puntatori a funzione (con  un puntatore a funzione (handler) che ha come
parametri due double) che restituiscono un parametro un int e come tipo restituito un void
puntatore a un array di 5 char e restituisce un puntatore a funzione che ha
 char *(*(*x[N])())() come argomento un int e restituisce un void
x è un array di N puntatori a funzione che
restituiscono un puntatore a funzione che
restituiscono un puntatore a char

7 8

Argomenti nella riga di comando Argomenti nella riga di comando


 Permettono di passare al programma dei valori  Bisogna definire il main in uno di questi modi:
dalla riga di comando (di shell)  main(int argc, char *argv[])
C:\>stampav ciao come va
 main(int argc, char **argv)
x
C:\>stampav ciao come va
Viene automaticamente creato un vettore di
ciao puntatori a stringhe, ciascuna delle quali
come
va
contiene uno degli argomenti. In dettaglio:
C:\>_  argc è il numero di elementi sulla riga di
comando, incluso il nome del comando
 argv è un puntatore ad un vettore di puntatori a
carattere: contiene gli indirizzi delle singole
stringhe che costituiscono la riga di comando.
L’ultimo elemento del vettore è sempre NULL
9 10

Argomenti nella riga di comando Argomenti nella riga di comando


 La struttura prodotta per argv è la seguente  Quindi nell’esempio:
 argc è il numero di parametri, incluso il comando
argv
stampav\0 (il nome del programma), vale 4
argv[0]  argv[0] è il nome del programma (“stampav”)
ciao\0  argv[1] è il primo parametro (“ciao”)
argv[1]  argv[2] è il secondo parametro (“come”)
argc
4 come\0  argv[3] è il terzo parametro (“va”)
argv[2]  argv[argc] è il terminatore NULL

argv[3]
va\0  E’ importante verificare sempre che il numero
di parametri effettivamente passati sia
NULL
concorde con quanto richiede il programma
argv[4]

11 12

Parsing della riga di comando Parsing della riga di comando


 Esempio di stampav: visualizza in colonna  Esempio di stampav: visualizza in colonna
tutti gli argomenti passati sulla riga di tutti gli argomenti passati sulla riga di
comando (1o modo) comando (2o modo)
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
int i; while (--argc > 0)
for (i=1; i<argc; i++) printf("%s\n", *++argv)
printf("%s\n", argv[i]) return EXIT_SUCCESS;
return EXIT_SUCCESS; }
} N.B. Questo programma funziona con
N.B. Questo programma funziona con qualsiasi numero di argomenti
qualsiasi numero di argomenti
13 14

Parsing della riga di comando Parsing della riga di comando


 Altro esempio: programma che elabora il file  Gli argomenti sulla riga di comando sono
indicato sulla riga di comando (se c’è) stringhe, per ottenere il valore numerico nel
main(int argc, char *argv[]) caso si trattino di numeri, si possono usare le
{ già citate funzioni seguenti (<stdlib.h>):
FILE *fp;  varInt = atoi(stringa)
if (argc = = 2)  controllo n. argomenti converte stringa in un valore int
{  varLong = atol(stringa)
if ((fp=fopen(argv[1],"r"))== NULL) converte stringa in un valore long
{  varDouble = atof(stringa)
fprintf ("File %s non aperto\n", converte stringa in un valore double
argv[1]);
return EXIT_FAILURE;
}

15 16

Spazi dei nomi Spazi dei nomi


 Gli identificatori ricadono in quattro  Questo spiega per quale motivo sia possibile
namespace (spazi dei nomi) differenti che non (e non infrequente) una dichiarazione quale:
interferiscono reciprocamente, anche quando typedef struct XYZ
sono nello stesso scope: {
 namespace degli oggetti (variabili, costanti, …), int x;
funzioni, nomi typedef, costanti enum int y;
 namespace delle etichette int z;
 namespace dei tag (di struct, union ed enum) } XYZ;
 namespace dei membri (ogni singola struct e
ogni singola union ha il suo namespace)
 Quindi è possibile che contemporaneamente
esistano (senza interferenze) una variabile,
un’etichetta, un tag e un membro (o più se di
diverse struct) con lo stesso identico nome
17 18

Assert Abort
 Macro per il debug definita in <assert.h>  Manda su stderr (in console mode) il
void assert(int condizione); messaggio “abnormal program termination” e
 Se la condizione è diversa da 0 (condizione quindi invoca la funzione raise(SIGABRT).
soddisfatta) il programma continua L’azione di default per SIGABRT è di
 Se la condizione è pari a 0 (condizione fallita): terminare il processo e restituire un exit code
 viene mandato su stderr (in console mode) un di valore 3
messaggio contenente: la condizione stessa, il
nome del file e il numero della riga dove è stata  abort();
valutata l’assert  Non restituisce alcun valore
 viene invocata la funzione abort per terminare il
programma con segnalazione di anomalia  Non fa il flush dei buffer e non chiama le
 Tutte le macro assert possono essere funzioni di atexit
disabilitata definendo la costante NDEBUG  Definita in <stdlib.h>
prima della #include<assert.h>

19 20

Atexit Atexit
 Registra i nomi delle funzioni da chiamare #include <stdlib.h>
automaticamente poco prima della #include <stdio.h>
terminazione normale del programma void fn1() { printf("dopo\n"); }
(return, exit()) void fn2() { printf("viene "); }
 atexit(nomeFunzione) void fn3() { printf("Questo "); }
 nomeFunzione è l’indirizzo di una funzione
(nome o puntatore) con prototipo main()
void nomeFunzione(void)
{ atexit(fn1);
 Ogni chiamata registra una funzione, le atexit(fn2);
funzioni vengono chiamate in ordine LIFO
atexit(fn3);
 Restituisce 0 se OK, !=0 se c’è qualche errore printf("Questo viene prima\n");
 Definita in <stdlib.h> }
21 22

Esercizi Esercizi
1. Scrivere un programma denominato calcola 2. Scrivere un programma denominato cat che
che richieda 3 parametri sulla riga di concateni tutti i file (di testo) passati sulla riga
comando: di comando (tranne l’ultimo) nell’ultimo file
1. operando 1 indicato:
2. operatore (+,-,*,/) cat file1 file2 ... file
3. operando 2 concatena file1, file2, ... in file
e calcoli: op1 oper op2. N.B. i file da concatenare potrebbero non
In caso di errore (numero parametri scorretto avere il ritorno a capo in fondo all’ultima riga,
o operatore non riconosciuto) lo segnali. lo si aggiunga se manca (non per l’ultimo file
Esempio da concatenare)
c:\> calcola 12 * 5
60