Correzioni varie e riscrittura di parte del capitolo 2
[gapil.git] / filestd.tex
index 14867d51305f3577f41127638d4698390ee0e167..a106ff579ec7a447e9e54f1d40bd345e54bd2c92 100644 (file)
@@ -89,14 +89,14 @@ questi tre stream sono identificabili attraverso dei nomi simbolici
 definiti nell'header \file{stdio.h} che sono:
 
 \begin{itemize}
-\item \var{FILE * stdin} Lo \textit{standard input} cioè lo stream da
+\item \var{FILE *stdin} Lo \textit{standard input} cioè lo stream da
   cui il processo riceve ordinariamente i dati in ingresso. Normalmente
   è associato dalla shell all'input del terminale e prende i caratteri
   dalla tastiera.
-\item \var{FILE * stdout} Lo \textit{standard input} cioè lo stream su
+\item \var{FILE *stdout} Lo \textit{standard input} cioè lo stream su
   cui il processo invia ordinariamente i dati in uscita. Normalmente è
   associato dalla shell all'output del terminale e scrive sullo schermo.
-\item \var{FILE * stderr} Lo \textit{standard input} cioè lo stream su
+\item \var{FILE *stderr} Lo \textit{standard input} cioè lo stream su
   cui il processo è supposto inviare i messaggi di errore. Normalmente
   anch'esso è associato dalla shell all'output del terminale e scrive
   sullo schermo.
@@ -215,12 +215,11 @@ tre\footnote{\func{fopen} e \func{freopen} fanno parte dello standard
 prototipi sono:
 \begin{functions}
   \headdecl{stdio.h}
-  \funcdecl{FILE * fopen(const char * path, const char *mode)}
+  \funcdecl{FILE *fopen(const char *path, const char *mode)}
   Apre il file specificato da \param{path}.
-  \funcdecl{FILE * fdopen(int fildes, const char * mode)}
+  \funcdecl{FILE *fdopen(int fildes, const char *mode)}
   Associa uno stream al file descriptor \param{fildes}.
-  \funcdecl{FILE * freopen(const char * path, const char * mode, FILE *
-  stream)}
+  \funcdecl{FILE *freopen(const char *path, const char *mode, FILE *stream)}
   Apre il file specificato da \param{path} associandolo allo stream
   specificato da \param{stream}, se questo è già aperto prima lo chiude.
   
@@ -335,11 +334,11 @@ una operazione nominalmente nulla come \func{fseek(file, 0, SEEK\_CUR)} 
 sufficiente a garantire la sincronizzazione.
 
 Una volta aperto lo stream, si può cambiare la modalità di bufferizzazione
-(vedi \secref{sec:file_buffering_ctrl}) fintanto che non si è effettuato
+(si veda \secref{sec:file_buffering_ctrl}) fintanto che non si è effettuato
 alcuna operazione di I/O sul file.
 
 Uno stream viene chiuso con la funzione \func{fclose} il cui prototipo è:
-\begin{prototype}{stdio.h}{int fclose(FILE * stream)}
+\begin{prototype}{stdio.h}{int fclose(FILE *stream)}
   Chiude lo stream \param{stream}. 
   
   \bodydesc{Restituisce 0 in caso di successo e \macro{EOF} in caso di errore,
@@ -349,12 +348,12 @@ Uno stream viene chiuso con la funzione \func{fclose} il cui prototipo 
     \func{fflush}).}
 \end{prototype}
 
-La funzione effettua uno scarico di tutti i dati presenti nei buffer di
-uscita e scarta tutti i dati in ingresso, se era stato allocato un
-buffer per lo stream questo verrà rilasciato. La funzione effettua lo
-scarico solo per i dati presenti nei buffer in user space usati dalle
-\acr{glibc}; se si vuole essere sicuri che il kernel forzi la scrittura
-su disco occorrerà effettuare una \func{sync}.
+La funzione effettua lo scarico di tutti i dati presenti nei buffer di uscita
+e scarta tutti i dati in ingresso; se era stato allocato un buffer per lo
+stream questo verrà rilasciato. La funzione effettua lo scarico solo per i
+dati presenti nei buffer in user space usati dalle \acr{glibc}; se si vuole
+essere sicuri che il kernel forzi la scrittura su disco occorrerà effettuare
+una \func{sync} (vedi \secref{sec:file_sync}).
 
 Linux supporta, come estensione implementata dalle \acr{glibc}, anche una
 altra funzione, \func{fcloseall}, che serve a chiudere tutti i file, il suo
@@ -364,12 +363,12 @@ prototipo 
   
   \bodydesc{Restituisce 0 se non ci sono errori ed \macro{EOF} altrimenti.}
 \end{prototype}
-la funzione esegue lo scarico dei dati bufferizzati in uscita e scarta quelli
-in ingresso, chiudendo tutti i file. Questa funzione è provvista solo per i
-casi di emergenza, quando si è verificato un errore ed il programma deve
-essere abortito, ma si vuole compiere qualche altra operazione dopo aver
-chiuso i file e prima di uscire (si ricordi quanto visto in
-\secref{sec:proc_exit}).
+\noindent la funzione esegue lo scarico dei dati bufferizzati in uscita
+e scarta quelli in ingresso, chiudendo tutti i file. Questa funzione è
+provvista solo per i casi di emergenza, quando si è verificato un errore
+ed il programma deve essere abortito, ma si vuole compiere qualche altra
+operazione dopo aver chiuso i file e prima di uscire (si ricordi quanto
+visto in \secref{sec:proc_exit}).
 
 
 \subsection{Lettura e scrittura su uno stream}
@@ -423,9 +422,9 @@ questi due flag possono essere riletti dalle funzioni:
   Controlla il flag di end-of-file di \param{stream}.
   \funcdecl{int ferror(FILE *stream)}
   Controlla il flag di errore di \param{stream}.
-
-  Entrambe le funzioni ritornano un valore diverso da zero se i relativi
-  flag sono settati. 
+  
+  \bodydesc{Entrambe le funzioni ritornano un valore diverso da zero se
+    i relativi flag sono settati.}
 \end{functions}
 \noindent si tenga presente comunque che la lettura di questi flag segnala
 soltanto che c'è stato un errore, o che si è raggiunta la fine del file in una
@@ -453,11 +452,11 @@ formattati. Le due funzioni che si usano per l'I/O binario sono:
 \begin{functions}
   \headdecl{stdio.h} 
   
-  \funcdecl{size\_t fread(void * ptr, size\_t size, size\_t nmemb, FILE
-    * stream)}
+  \funcdecl{size\_t fread(void *ptr, size\_t size, size\_t nmemb, FILE
+    *stream)}
   
-  \funcdecl{size\_t fwrite(const void * ptr, size\_t size, size\_t
-    nmemb, FILE * stream)}
+  \funcdecl{size\_t fwrite(const void *ptr, size\_t size, size\_t
+    nmemb, FILE *stream)}
   
   Rispettivamente leggono e scrivono \param{nmemb} elementi di dimensione
   \param{size} dal buffer \param{ptr} al file \param{stream}.
@@ -472,7 +471,7 @@ blocchi di dati binari in maniera compatta e veloce; un primo caso di uso
 tipico è quello in cui si salva un vettore (o un certo numero dei suoi
 elementi) con una chiamata del tipo:
 \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
-int WriteVect(FILE * stream, double * vec, size_t nelem) 
+int WriteVect(FILE *stream, double *vec, size_t nelem) 
 {
     int size, nread;
     size = sizeof(*vec);
@@ -552,11 +551,11 @@ gestione delle applicazioni multi-thread (si veda
 \begin{functions}
   \headdecl{stdio.h} 
   
-  \funcdecl{size\_t fread\_unlocked(void * ptr, size\_t size, size\_t
-    nmemb, FILE * stream)}
+  \funcdecl{size\_t fread\_unlocked(void *ptr, size\_t size, size\_t
+    nmemb, FILE *stream)}
   
-  \funcdecl{size\_t fwrite\_unlocked(const void * ptr, size\_t size,
-    size\_t nmemb, FILE * stream)}
+  \funcdecl{size\_t fwrite\_unlocked(const void *ptr, size\_t size,
+    size\_t nmemb, FILE *stream)}
   
   \bodydesc{Le funzioni sono identiche alle analoghe \func{fread} e
     \func{fwrite} ma non acquisiscono il lock implicito sullo stream.}
@@ -614,6 +613,7 @@ byte restituiscono un carattere in formato esteso (cio
 \type{wint\_t}, il loro prototipo è:
 \begin{functions}
   \headdecl{stdio.h} 
+  \headdecl{wchar.h} 
   
   \funcdecl{wint\_t getwc(FILE *stream)} Legge un carattere esteso da
   \param{stream}. In genere è implementata come una macro.
@@ -653,9 +653,10 @@ sempre un intero; in caso di errore o fine del file il valore di ritorno
 è \macro{EOF}.
 
 Come nel caso dell'I/O binario le \acr{glibc} provvedono per ciascuna
-delle funzioni precedenti una seconda funzione, il cui nome è ottenuto
-aggiungendo un \func{\_unlocked}, che esegue esattamente le stesse
-operazioni evitando però il lock implicito dello stream.
+delle funzioni precedenti, come estensione GNU, una seconda funzione, il
+cui nome è ottenuto aggiungendo un \func{\_unlocked}, che esegue
+esattamente le stesse operazioni evitando però il lock implicito dello
+stream.
 
 Per compatibilità con SVID sono provviste anche due funzioni per leggere
 e scrivere una \textit{word} (che è sempre definita come \type{int}); i
@@ -692,11 +693,11 @@ lettura si chiama \func{ungetc} ed il suo prototipo 
   \bodydesc{La funzione ritorna \param{c} in caso di successo e
   \macro{EOF} in caso di errore.}
 \end{prototype}
-benché lo standard ANSI C preveda che l'operazione possa essere ripetuta
-per un numero arbitrario di caratteri, alle implementazioni è richiesto
-di garantire solo un livello; questo è quello che fa la \acr{glibc}, che
-richiede che avvenga un'altra operazione fra due \func{ungetc}
-successive.
+\noindent benché lo standard ANSI C preveda che l'operazione possa
+essere ripetuta per un numero arbitrario di caratteri, alle
+implementazioni è richiesto di garantire solo un livello; questo è
+quello che fa la \acr{glibc}, che richiede che avvenga un'altra
+operazione fra due \func{ungetc} successive.
 
 Non è necessario che il carattere che si manda indietro sia l'ultimo che
 si è letto, e non è necessario neanche avere letto nessun carattere
@@ -722,36 +723,400 @@ scartati.
 \subsection{Input/output di linea}
 \label{sec:file_line_io}
 
-La terza ed ultima modalità di input/output non formattato è quello di
+La terza ed ultima modalità di input/output non formattato è quella di
 linea, in cui legge o scrive una riga alla volta; questa è una modalità
 molto usata per l'I/O da terminale, ma che presenta le caratteristiche
 più controverse.
 
-Le funzioni per leggere una linea sono sostanzialmente due, \func{gets} e
-\func{fgets}, i cui rispettivi prototipi sono:
+Le funzioni previste dallo standard ANSI C per leggere una linea sono
+sostanzialmente due, \func{gets} e \func{fgets}, i cui rispettivi
+prototipi sono:
 \begin{functions}
   \headdecl{stdio.h} 
   
-  \funcdecl{char * gets(char * string)} Scrive su \param{string} una
+  \funcdecl{char *gets(char *string)} Scrive su \param{string} una
   linea letta da \var{stdin}.
   
-  \funcdecl{char * fgets(char * string, int size, FILE *stream)}
+  \funcdecl{char *fgets(char *string, int size, FILE *stream)}
   Scrive su \param{string} la linea letta da \param{stream} per un
   massimo di \param{size} byte.
   
-  \bodydesc{Le funzioni restituiscono della stringa letta o \macro{NULL}
-    in caso di errore.}
+  \bodydesc{Le funzioni restituiscono l'indirizzo \param{string} in caso
+    di successo o \macro{NULL} in caso di errore.}
+\end{functions}
+
+Entrambe le funzioni effettuano la lettura (dal file specificato
+\func{fgets}, dallo standard input \func{gets}) di una linea di
+caratteri (terminata dal carattere \textit{newline}, \verb|\n|), ma
+\func{gets} sostituisce \verb|\n| con uno zero, mentre \func{fgets}
+aggiunge uno zero dopo il \textit{newline}, che resta dentro la
+stringa. Se la lettura incontra la fine del file (o c'è un errore) viene
+restituito un \macro{NULL}, ed il buffer \param{buf} non viene toccato.
+
+L'uso di \func{gets} è deprecato e deve essere assolutamente evitato; la
+funzione infatti non controlla il numero di byte letti, per cui nel caso
+la stringa letta superi le dimensioni del buffer, si avrà un
+\textit{buffer overflow}, con sovrascrittura della memoria del processo
+adiacente al buffer. 
+
+Questa è una delle vulnerabilità più sfruttate per guadagnare accessi
+non autorizzati al sistema (i cosiddetti \textit{exploit}), basta
+infatti inviare una stringa sufficientemente lunga ed opportunamente
+forgiata per sovrascrivere gli indirizzi di ritorno nello stack
+(supposto che la \func{gets} sia stata chiamata da una subroutine), in
+modo da far ripartire l'esecuzione nel codice inviato nella stringa
+stessa (in genere uno \textit{shell code} cioè una sezione di programma
+lancia una shell).
+
+La funzione \func{fgets} non ha i precedenti problemi di \func{gets} in
+quanto prende in input la dimensione del buffer \param{size}, che non
+verrà mai ecceduta in lettura. La funzione legge fino ad un massimo di
+\param{size} caratteri (newline compreso), ed aggiunge uno zero di
+terminazione; questo comporta che la stringa possa essere al massimo di
+\var{size-1} caratteri.  Se la linea eccede la dimensione del buffer
+verranno letti solo \var{size-1} caratteri, ma la stringa sarà sempre
+terminata correttamente con uno zero finale; sarà possibile leggere i
+restanti caratteri in una chiamata successiva.
+
+Per la scrittura di una linea lo standard ANSI C prevede altre due
+funzioni, \func{fputs} e \func{puts}, analoghe a quelle di lettura, i
+rispettivi prototipi sono:
+\begin{functions}
+  \headdecl{stdio.h} 
+  
+  \funcdecl{int puts(const char *string)} Scrive su \var{stdout} la
+  linea \param{string}.
+  
+  \funcdecl{int fputs(const char *string, FILE *stream)} Scrive su
+  \param{stream} la linea \param{string}.
+  
+  \bodydesc{Le funzioni restituiscono un valore non negativo in caso di
+    successo o \macro{EOF} in caso di errore.}
 \end{functions}
 
+Dato che in questo caso si scrivono i dati in uscita \func{puts} non ha
+i problemi di \func{gets} ed è in genere la forma più immediata per
+scrivere messaggi sullo standard output; la funzione prende una stringa
+terminata da uno zero ed aggiunge automaticamente un newline. La
+differenza con \func{fputs} (a parte la possibilità di specificare un
+file diverso da \var{stdout}) è che quest'ultima non aggiunge il
+newline, che deve essere previsto esplicitamente. 
+
+Come per le funzioni di input/output a caratteri esistono le estensioni
+per leggere e scrivere caratteri estesi, i loro prototipi sono:
+\begin{functions}
+  \headdecl{wchar.h} 
+  \funcdecl{wchar\_t *fgetws(wchar\_t *ws, int n, FILE *stream)}
+  Legge un massimo di \param{n} caratteri estesi dal file
+  \param{stream} al buffer \param{ws}.
+  
+  \funcdecl{int fputws(const wchar\_t *ws, FILE *stream)} Scrive la
+  linea \param{ws} di caratteri estesi sul file \param{stream}.
+  
+  \bodydesc{Le funzioni ritornano rispettivamente \param{ws} o un numero
+    non negativo in caso di successo e \macro{NULL} o \macro{EOF} in
+    caso di errore o fine del file.}
+\end{functions}
+\noindent il comportamento è identico a quello di \func{fgets} e
+\func{fputs} solo che tutto (numero di caratteri massimo, terminatore
+della stringa, newline) è espresso in termini di caratteri estesi
+anziché di caratteri ASCII.
+
+Come nel caso dell'I/O binario e a caratteri nelle \acr{glibc} sono
+previste una serie di altre funzioni, estensione di tutte quelle
+illustrate finora (eccetto \func{gets} e \func{puts}), il cui nome si
+ottiene aggiungendo un \func{\_unlocked}, e che eseguono esattamente le
+stesse operazioni delle loro equivalenti, evitando però il lock
+implicito dello stream (vedi \secref{sec:file_stream_thread}).
+
+Come abbiamo visto, le funzioni di lettura per l'input/output di linea
+previste dallo standard ANSI C presentano svariati inconvenienti. Benché
+\func{fgets} non abbia i gravissimi problemi di \func{gets}, può
+comunque dare risultati ambigui se l'input contiene degli zeri; questi
+infatti saranno scritti sul buffer di uscita e la stringa in output
+apparirà come più corta dei byte effettivamente letti. Questa è una
+condizione che è sempre possibile controllare (deve essere presente un
+newline prima della effettiva conclusione della stringa presente nel
+buffer), ma a costo di una complicazione ulteriore della logica del
+programma. Lo stesso dicasi quando si deve gestire il caso di stringa
+che eccede le dimensioni del buffer.
+
+Per questo motivo le \acr{glibc} prevedono, come estensione GNU, due
+nuove funzioni per la gestione dell'input/output di linea, il cui uso
+permette di risolvere questi problemi. L'uso di queste funzioni deve
+essere attivato definendo la macro \macro{\_GNU\_SOURCE} prima di
+includere \file{stdio.h}. La prima delle due, \func{getline}, serve per
+leggere una linea terminata da un newline esattamente allo stesso modo
+di \func{fgets}, il suo prototipo è:
+\begin{prototype}{stdio.h}
+  {ssize\_t getline(char **buffer, size\_t *n, FILE *stream)} Legge una
+  linea dal file \param{stream} sul buffer indicato da \param{buffer}
+  riallocandolo se necessario (l'indirizzo del buffer e la sua
+  dimensione vengono sempre riscritte).
+
+  \bodydesc{La funzione ritorna il numero di caratteri letti in caso di
+  successo e -1 in caso di errore o di raggiungimento della fine del
+  file.}
+\end{prototype}
+
+La funzione permette di eseguire una lettura senza doversi preoccupare
+della eventuale lunghezza eccessiva della stringa da leggere. Essa
+prende come primo parametro l'indirizzo del puntatore al buffer su cui
+si vuole leggere la linea. Quest'ultimo \emph{deve} essere stato
+allocato in precedenza con una \func{malloc} (non si può passare
+l'indirizzo di un puntatore ad una variabile locale); come secondo
+parametro la funzione vuole l'indirizzo della variabile contenente le
+dimensioni del buffer suddetto.
+
+Se il buffer di destinazione è sufficientemente ampio la stringa viene
+scritta subito, altrimenti il buffer viene allargato usando
+\func{realloc} e la nuova dimensione ed il nuovo puntatore vengono
+passata indietro (si noti infatti come per entrambi i parametri si siano
+usati dei \textit{value result argument}, passando dei puntatori anzichè
+i valori delle variabili, secondo la tecnica spiegata in
+\secref{sec:proc_var_passing}).
+
+Se si passa alla funzione l'indirizzo ad un puntatore settato a
+\macro{NULL} e \var{*n} è zero, la funzione provvede da sola
+all'allocazione della memoria necessaria a contenere la linea. In tutti
+i casi si ottiene dalla funzione un puntatore all'inizio del testo della
+linea. Un esempio di codice può essere il seguente:
+\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+    size_t n = 0; 
+    char *ptr = NULL;
+    int nread;
+    FILE * file;
+    ...    
+    nread = getline(&ptr, &n, file);
+\end{lstlisting}
+e per evitare memory leak occorre ricordarsi di liberare \var{ptr} con
+una \func{free}.
+
+Il valore di ritorno della funzione indica il numero di caratteri letti
+dallo stream (quindi compreso il newline, ma non lo zero di
+terminazione); questo permette anche di distinguere eventuali zeri letti
+dallo stream da quello inserito dalla funzione per terminare la linea.
+Se si è alla fine del file e non si è potuto leggere nulla o c'è stato
+un errore la funzione restituisce -1.
+
+La seconda estensione GNU è una generalizzazione di \func{getline} per
+poter usare come separatore un carattere qualsiasi, la funzione si
+chiama \func{getdelim} ed il suo prototipo è:
+\begin{prototype}{stdio.h}
+{ssize\_t getdelim(char **buffer, size\_t *n, int delim, FILE *stream)} 
+  Identica a \func{getline} solo che usa \param{delim} al posto del
+  carattere di newline come separatore di linea.
+\end{prototype}
+
+Il comportamento di \func{getdelim} è identico a quello di
+\func{getline} (che può essere implementata da questa passando
+\verb|'\n'| come valore di \param{delim}).
 
 
 \subsection{Input/output formattato}
 \label{sec:file_formatted_io}
 
+L'ultima modalità di input/output è quella formattata, che è una delle
+caratteristiche più utilizzate delle librerie standard del C; in genere
+questa è la modalità in cui si esegue normalmente l'output su terminale
+poichè permette di stampare in maniera facile e veloce dati, tabelle e
+messaggi.
+
+L'output formattato viene eseguito con una delle 13 funzioni della
+famiglia \func{printf}; le tre più usate sono le seguenti:
+\begin{functions}
+  \headdecl{stdio.h} 
+  \funcdecl{int printf(const char *format, ...)} Stampa su \var{stdout}
+  gli argomenti, secondo il formato specificato da \param{format}.
+  
+  \funcdecl{int fprintf(FILE *stream, const char *format, ...)}  Stampa
+  su \param{stream} gli argomenti, secondo il formato specificato da
+  \param{format}.
+  
+  \funcdecl{int sprintf(char *str, const char *format, ...)} Stampa
+  sulla stringa \param{str} gli argomenti, secondo il formato
+  specificato da \param{format}.
+
+  \bodydesc{Le funzioni ritornano il numero di caratteri stampati.}
+\end{functions}
+\noindent le prime due servono per stampare su file (lo standard output
+o quello specificato) la terza permette di stampare su una stringa, in
+genere l'uso di \func{sprintf} è sconsigliato in quanto è possibile, se
+non si ha la sicurezza assoluta sulle dimensioni del risultato della
+stampa, eccedere le dimensioni di \param{str}; per questo motivo si
+consiglia l'uso dell'alternativa:
+\begin{prototype}{stdio.h}
+{snprintf(char *str, size\_t size, const char *format, ...);} 
+  Identica a \func{sprintf}, ma non scrive su \param{str} più di
+  \param{size} caratteri.
+\end{prototype}
+
+La parte più complessa di queste funzioni è il formato della stringa
+\param{format} che indica le conversioni da fare, da cui poi deriva il numero
+dei parametri che dovranno essere passati a seguire. La stringa è costituita
+da caratteri normali (tutti eccetto \texttt{\%}), che vengono passati
+invariati all'output, e da direttive di conversione, in cui devono essere
+sempre presenti il carattere \texttt{\%}, che introduce la direttiva, ed uno
+degli specificatori di conversione (riportati in \ntab) che la conclude. 
+
+\begin{table}[htb]
+  \centering
+  \begin{tabular}[c]{|l|l|p{10cm}|}
+    \hline
+    \textbf{Valore} & \textbf{Tipo} & \textbf{Significato} \\
+    \hline
+    \hline
+   \cmd{\%d} &\type{int}         & Stampa un numero intero in formato decimale
+                                   con segno \\
+   \cmd{\%i} &\type{int}         & Identico a \cmd{\%i} in output, \\
+   \cmd{\%o} &\type{unsigned int}& Stampa un numero intero come ottale\\
+   \cmd{\%u} &\type{unsigned int}& Stampa un numero intero in formato
+                                   decimale senza segno \\
+   \cmd{\%x}, 
+   \cmd{\%X} &\type{unsigned int}& Stampano un intero in formato esadecimale,
+                                   rispettivamente con lettere minuscole e
+                                   maiuscole. \\
+   \cmd{\%f} &\type{unsigned int}& Stampa un numero in virgola mobile con la
+                                   notazione a virgola fissa \\
+   \cmd{\%e}, 
+   \cmd{\%E} &\type{double} & Stampano un numero in virgola mobile con la
+                              notazione esponenziale, rispettivamente con
+                              lettere minuscole e maiuscole. \\
+   \cmd{\%g}, 
+   \cmd{\%G} &\type{double} & Stampano un numero in virgola mobile con la
+                              notazione più appropriate delle due precedenti,
+                              rispettivamente con lettere minuscole e
+                              maiuscole. \\
+   \cmd{\%a}, 
+   \cmd{\%A} &\type{double} & Stampano un numero in virgola mobile in
+                              notazione esadecimale frazionaria\\
+   \cmd{\%c} &\type{int}    & Stampa un carattere singolo\\
+   \cmd{\%s} &\type{char *} & Stampa una stringa \\
+   \cmd{\%p} &\type{void *} & Stampa il valore di un puntatore\\
+   \cmd{\%n} &\type{\&int}  & Prende il numero di caratteri stampati finora\\
+   \cmd{\%\%}&              & Stampa un \% \\
+    \hline
+  \end{tabular}
+  \caption{Valori possibili per gli specificatori di conversione in una
+    stringa di formato di \func{printf}.} 
+  \label{tab:file_format_spec}
+\end{table}
+
+
+Il formato di una direttiva di conversione prevede una serie di possibili
+elementi opzionali oltre al \cmd{\%} e allo specificatore di conversione; in
+generale essa è sempre del tipo:
+\begin{center}
+\begin{verbatim}
+% [n. parametro $] [flag] [[larghezza] [. precisione]] [tipo] conversione
+\end{verbatim}
+\end{center}
+in cui i valori opzionali sono indicati fra parentesi, e prevedono la
+presenza, in questo ordine, di: uno specificatore per il parametro da usare
+(terminato da un \cmd{\$}, uno o più flag (riassunti in
+\tabref{tab:file_format_flag}) che controllano il formato di stampa della
+conversione (riassunti in \tabref{tab:file_format_type}), uno specificatore di
+larghezza, eventualmente seguito (per i numeri in virgola mobile) da un
+specificatore di precisione, uno specificatore del tipo di dato (che ne indica
+la lunghezza).
+
+\begin{table}[htb]
+  \centering
+  \begin{tabular}[c]{|l|p{10cm}|}
+    \hline
+    \textbf{Valore} & \textbf{Significato}\\
+    \hline
+    \hline
+    \cmd{\#}  & \\
+    \cmd{0}   & \\
+    \cmd{-}   & \\
+    \cmd{' '} & \\
+    \cmd{+}   & \\
+    \hline
+  \end{tabular}
+  \caption{I valori dei flag per il formato di \func{printf}}
+  \label{tab:file_format_flag}
+\end{table}
+
+
+
+\begin{table}[htb]
+  \centering
+  \begin{tabular}[c]{|l|p{10cm}|}
+    \hline
+    \textbf{Valore} & \textbf{Significato} \\
+    \hline
+    \hline
+    \cmd{hh} & \\
+    \cmd{h}  & \\
+    \cmd{l}  & \\
+    \cmd{ll} & \\
+    \cmd{L}  & \\
+    \cmd{q}  & \\
+    \cmd{j}  & \\
+    \cmd{z}  & \\
+    \cmd{t}  & \\
+    \hline
+  \end{tabular}
+  \caption{Il modificatore di tipo di dato per il formato di \func{printf}}
+  \label{tab:file_format_type}
+\end{table}
+
+
+
+
 
 \subsection{Posizionamento su uno stream}
 \label{sec:file_fseek}
 
+Come per i file descriptor è possibile anche con gli stream spostarsi
+all'interno di un file per effettuare operazioni di lettura o scrittura in un
+punto prestabilito; questo fintanto che l'operazione di riposizionamento è
+supportata dal file sottostante lo stream, quando cioè si ha a che fare con
+quello che viene detto un file ad \textsl{accesso casuale}.
+
+In GNU/Linux ed in generale in ogni sistema unix-like la posizione nel
+file è espressa da un intero positivo, rappresentato dal tipo
+\type{off\_t}, il problema è alcune delle funzioni usate per il
+riposizionamento sugli stream originano dalle prime versioni di unix in
+cui questo tipo non era ancora stato definito, e che in altri sistemi
+non è detto che la posizione su un file venga sempre rappresentata con
+un numero di caratteri (ad esempio in VMS può essere rappresentata come
+numero di record, e offset rispetto al record corrente).
+
+Tutto questo comporta la presenza di diverse funzioni che eseguono
+sostanzialmente le stesse operazioni, ma usano parametri di tipo
+diverso. Le funzioni tradizionali usate per il riposizionamento della
+posizione in uno stream sono:
+\begin{functions}
+  \headdecl{stdio.h} 
+  
+  \funcdecl{int fseek(FILE *stream, long offset, int whence)} Sposta la
+  posizione nello stream secondo quanto specificato tramite \param{offset}
+  e \param{whence}.  
+
+  \funcdecl{void rewind(FILE *stream)} Riporta la posizione nello stream
+  all'inizio del file.
+\end{functions}
+
+L'uso di \func{fseek} è del tutto analogo a quello di \func{lseek} per i
+file descriptor, ed i parametri, a parte il tipo, hanno lo stesso
+significato; in particolare \param{whence} assume gli stessi valori già
+visti in \secref{sec:file_lseek}. La funzione restituisce 0 in caso di
+successo e -1 in caso di errore. 
+
+Per leggere la posizione corrente si usa invece la funzione \func{ftell}, il
+cui prototipo è:
+\begin{prototype}{stdio.h}{long ftell(FILE *stream)} 
+  Legge la posizione attuale nello stream.
+  
+  \bodydesc{La funzione restituisce la posizione corrente, o -1 in caso
+    di fallimento, che può esser dovuto sia al fatto che il file non
+    supporta il riposizionamento che al fatto che la posizione non può
+    essere espressa con un \type{long int}}
+\end{prototype}
+
+  
 
 
 \section{Funzioni avanzate}
@@ -779,10 +1144,10 @@ stream; questo pu
 \func{\_\_fwritable} i cui prototipi sono:
 \begin{functions}
   \headdecl{stdio\_ext.h}
-  \funcdecl{int \_\_freadable (FILE * stream)}
+  \funcdecl{int \_\_freadable (FILE *stream)}
   Restituisce un valore diverso da zero se \param{stream} consente la lettura.
 
-  \funcdecl{int \_\_fwritable(FILE * stream)}  
+  \funcdecl{int \_\_fwritable(FILE *stream)}  
   Restituisce un valore diverso da zero se \param{stream} consente la
   scrittura.
 \end{functions}
@@ -791,11 +1156,11 @@ Altre due funzioni, \func{\_\_freading} e \func{\_\_fwriting} servono ad un
 uso ancora più specialistico, il loro prototipo è: 
 \begin{functions}
   \headdecl{stdio\_ext.h}
-  \funcdecl{int \_\_freading (FILE * stream)}
+  \funcdecl{int \_\_freading (FILE *stream)}
   Restituisce un valore diverso da zero se \param{stream} è aperto in sola
   lettura o se l'ultima operazione è stata di lettura.
 
-  \funcdecl{int \_\_fwriting(FILE * stream)}  
+  \funcdecl{int \_\_fwriting(FILE *stream)}  
   Restituisce un valore diverso da zero se \param{stream} è aperto in sola
   scrittura o se l'ultima operazione è stata di scrittura.
 \end{functions}
@@ -834,16 +1199,16 @@ pesantemente dalle richieste necessarie per garantirne l'uso coi thread.
 \begin{functions}
   \headdecl{stdio.h}
   
-  \funcdecl{void flockfile(FILE * stream)} Esegue l'acquisizione del
+  \funcdecl{void flockfile(FILE *stream)} Esegue l'acquisizione del
   lock dello stream \param{stream}, bloccandosi in caso il lock non
   disponibile. 
   
-  \funcdecl{int ftrylockfile(FILE * stream)} Tenta l'acquisizione del
+  \funcdecl{int ftrylockfile(FILE *stream)} Tenta l'acquisizione del
   lock dello stream \param{stream}, senza bloccarsi in caso il lock non sia
   disponibile. Ritorna zero in caso di acquisizione del lock, diverso da
   zero altrimenti.
   
-  \funcdecl{void funlockfile(FILE * stream)} Rilascia il lock dello
+  \funcdecl{void funlockfile(FILE *stream)} Rilascia il lock dello
   stream \param{stream}.
 \end{functions}