Newsgroup: it.comp.lang.c
Titolo: Input bufferizzato

Più volte ho sentito dire in questo NG che l'input da tastiera del C è
bufferizzato (cosa che ho notato anche di persona). Sapreste dirmi in che
modo il C può bufferizzare l'input? Che tecnica usa?
Grazie per le risposte, Giuseppe

modo il C puň bufferizzare l'input? Che tecnica usa?
In ogni implementazione di C esistono delle funzioni ad alto livello e
delle funzioni a basso livello per gestire l'input.
Le uniche standard sono quelle ad alto livello, che sfruttano, poi,
con ogni compilatore, quelle a basso livello.
La differenza sostanziale tra quelle ad alto livello e quelle a basso
livello e' che le prime utilizzano dei buffer interni per ottimizzare
l'accesso ai dati e le seconde no.
Nel caso di funzioni come getchar()/putchar() (implementate spesso
come macro di getc()/putc()) si dice che viene utilizzato un
"line-buffering", ovvero i buffer rispettivi vengono svuotati quando
si incontra un carattere che indica la fine di una linea ('\n'),
oppure nel caso di stream di output, mediante l'uso di fflush().
Esistono, comunque, due funzioni standard : setbuf() e setvbuf() che
servono a controllare il buffering degli stream.

Quello che non capisco io č come il programma riesca a bufferizzare l'input
ricevuto. Se il mio programma sta svolgendo altri compiti come fa a ricevere
l'input dalla tastiera e a memorizzarlo in un buffer? Installa dei vettori
di interrupt?
Qualcuno saprebbe chiarirmi questo dubbio?
Grazie, Giuseppe

Grazie per le risposte, Giuseppe
In realta' nel C non e' che si parli di "tastiera". In C puoi leggere dati
da files (come stdin) che sono bufferizzati.
Poi, se stdin e' mappato alla tastiera credo che la bufferizzazione (nelle
implementazioni DOS) venga fatta non tanto dal c quanto dal bios o dos, a
seconda di cosa usa il compilatore.
Marco

Marco
Allora il C utilizza il buffer di tastiera gestito dal BIOS? Non credo
perchè questo buffer è limitato a 16 caratteri mentre, sempre nel NG, ho
sentito che l'input viene bufferizzato fino a che non si incontra un
carattere '\n'. Come è possibile questo? Ci sarà un'altra spiegazione....
Spero di poter chiarire questo mio dilemma.
Ciao e grazie per le risposte, Giuseppe

Spero di poter chiarire questo mio dilemma.
Mi e' nuova. Pole essere (ma forse era una implementazione diversa dal
dos... quel \n mi ricorda tanto i terminali..).
Che implementazione usi?
Marco

l'input dalla tastiera e a memorizzarlo in un buffer? 
Quando il tuo programma ha necessita' di chiedere un carattere allo
stream di input lo fa mediante una funzione di lettura "ad alto
livello", la quale "bufferizza" in una zona di memoria che ha
precedentemente allocato (vedi getc()) tutto cio' che le viene
restituito dalla funzione "a basso livello" che interagisce con la
periferica di input.
Nel caso di getchar() (o getc(), visto che la prima e' solo una macro
del tipo getc(stdin)), la funzione "bufferizza" tutto cio' che le
viene passato da una funzione a basso livello sino a che non le viene
passata la sequenza (o il singolo carattere) che identifica la fine
della linea di input.
Questa tecnica consente di mantenere portabilita' tra i diversi
sistemi, dato che sotto Unix l'identificatore di fine linea e'
rappresentato da un solo carattere (LF) mentre sotto DOS da due
caratteri (CR+LF).
Il programmatore non deve preoccuparsi della gestione della fine della
linea di input mediante la scelta dell'uno o dell'altro sistema, ma si
affida semplicemente al riconoscimento della sequenza di escape \n.

 Qualcuno saprebbe chiarirmi questo dubbio?
Il C, in generale, si appoggerà ai servizi offerti dal sistema operativo
e quindi i dettagli su come avvenga il meccanismo di bufferizzazione al
livello da te richiesto non fanno parte dello standard e dipendono
quindi dal sistema utilizzato.
EMG

affida semplicemente al riconoscimento della sequenza di escape \n.
Questo concetto di portabilità l'ho capito.


Marco
In che senso che implementazione? Utilizzo un semplice PC con DOS e Win95.
Grazie per l'interessamento, Giuseppe

EMG
Il problema non è il metodo con cui il C riceve l'input dalla tastiera, ma
come fa a riceverlo mentre che il programma sta svolgendo altri compiti. Se
io sto facendo dei calcoli matematici complessi i tasti premuti durante
questi calcoli vengono persi. Ma se l'input del C è bufferizzato in teoria
non dovrei perderli. Qual'è il vero comportamento del C?


limitato a 16 caratteri, no?
Quello che si intende per "buffering" per le routine standard di input
del C non ha NULLA a che vedere con il buffering effettuato dal BIOS.

Questa non l'ho capita. Potresti spiegarmela meglio?
Piu' che una spiegazione, va bene un esempio.
Eseguendo il codice seguente prova a scrivere "Giuseppe" e a dare
Invio.
L'unica chiamata a getchar() che richiede l'intervento dell'utente e'
la prima, mentre le altre prelevano dal buffer.
#include <stdio.h>
main()
{
   int c ;
   while ( (c = getchar()) != '\n' ) printf ( "%c\n", c ) ;
   return 0 ;
}

non dovrei perderli. Qual'è il vero comportamento del C?
"Bufferizzato" non significa che lavora in asincrono con le altri
parti del programma, ma semplicemente che viene letto a blocchi e
restituito un carattere per volta.

In che senso che implementazione? Utilizzo un semplice PC con DOS e Win95.
Intendevo dire che compilatore. Penso il borland, comunque.
Marco


Questo dipende dal sistema operativo usato.
Nel dos alla pressione/rilascio di un tasto scatta un certo interrupt, che a
sua volta controlla la tastiera, vede che tasto hai premuto, se c'e' lo
shift o  meno ecc. ecc. e alla fine mette il codice nel buffer del bios.
Di tutto questo ovviamente il programma in C non ne sa niente. Quando lui
chiede un carattere va a vedere direttamente nel buffer di tastiera, gestito
dal bios.
Il tutto sotto dos, ma per altri sistemi (ad es. minix) il meccanismo
dovrebbe essere analogo.
Marco



restituito un carattere per volta.
Allora il problema è che intendevamo due cose diverse: io pensavo che
bufferizzato significasse memorizzato per essere letto quando seve
intendendo che 'qualsiasi' input venisse memorizzato, mentre invece l'input
viene bufferizzato solo quando vengono chiamate le funzioni a basso livello.
Ora ho capito... Grazie di tutto a coloro che si sono interessati a
rispondermi.
Grazie, Giuseppe

Marco
Ho già chiarito la mia posizione (avevo inteso un'altra cosa...) nella
risposta a Laforgia.
Comunque ora vorrei fare una considerazione su quello che hai detto tu. E'
vero che il C deve per forza di cose affidarsi al BIOS altrimenti perderebbe
la maggior parte dell'input non potendo stare continuamente in ascolto delle
porte relative alle periferiche di input, tuttavia ciò non lo rende per
nulla performante. Io lo noto ora perchè, cominciando a lavorare con la
grafica per poi passare ai giochi, sto avendo la necessità di scrivermi
delle librerie personali per la gestione della tastiera. Sarà giusto che per
mantenere la portabilità si debba rinunciare alla velocità? Io questa cosa
non l'ho mai digerita (non credo nella portabilità)......
Ciao e grazie per avermi aiutato a capire, Giuseppe

}
Questo programmino e il suo funzionamento l'ho capito (la prima chiamata
bufferizza l'input fino a '\n' e poi le altre chiamate prelevano dal buffer)
ma io mi riferivo ad un'altra funzione, sempre definita (ho controllato
negli header) come getc(stdin) di nome getch() presente in conio.h
(probabilmente non č standard...) che non credo proprio bufferizzi l'input
(legge il carattere premuto; se nessun carattere č stato premuto aspetta
fino a che non venga premuto un tasto; di solito viene utilizzata in
concomitanza con kbhit() ). Probabilmente č anche per questo che non ci
siamo intesi prima (giravamo attorno a due funzioni diverse; getchar č
palese che bufferizzi). Comunque grazie per aver dissipato questo mio
dubbio.
Grazie e ciao, Giuseppe

(probabilmente non è standard...) che non credo proprio bufferizzi l'input
No, aspetta, stai confondendo.
getc() e' una funzione standard ad alto livello che si comporta come
getchar(), o meglio, getchar() ha lo stesso funzionamento di getc() in
quanto e' una semplice ridefinizione mediante macro del tipo
getc(stdin).
getch() invece e' una funzione non standard di basso livello, ovvero
non soggetta al buffering proprio delle routine ad alto livello.
L'intera libreria conio.h non e' standard.

non l'ho mai digerita (non credo nella portabilità)......
Certo che e' giusto.
Non solo e' giusto ma e' addirittura necessario.
Lo standard di un linguaggio non puo' essere tale se non prescinde dai
dettagli implementativi.
Il C standard offre delle routine che possono essere utilizzate senza
problemi su diverse piattaforme e le estensioni del linguaggio,
fornite con ogni specifico compilatore, lo arrichiscono delle funzioni
a basso livello.
Il fatto, poi, di essere "performante" non dipende dal linguaggio in
se', anche se il C da solo offre un ottimo supporto alla
programmazione in termini di velocita', ma dall'implementazione delle
estensioni presenti con ogni compilatore.
E' ad esse, difatti, che devi far riferimento se vuoi scrivere
programmi non portabili come i giochi.
E' giusto che, in caso di necessita', tu sia costretto a scriverti le
tue routine, in quanto il C e' nato proprio con questo intento.
Forse tu non credi nella portabilita' perche' hai scritto sempre
programmi di ambito specifico, ma ti assicuro che e' vantaggiosa al
punto da rinunciare a qualcosa in termini di velocita'.
Non e' comunque detto che una maggiore portabilita' implichi una
minore velocita'.

 non dovrei perderli. Qual'è il vero comportamento del C?
Se il sistema sottostante può fornire tali caratteri nel momento in cui
vengono richiesti allora il C li legge e li bufferizza alla chiamata di
una qualsiasi funzione di lettura dello standard input.
EMG

non l'ho mai digerita (non credo nella portabilità)......
Non e' vero che la gestione dell'input da tastiera tramite interrupt non sia
performante, tutt'altro! Non puoi certo fare il polling, e altri metodi non
ce ne sono (a meno di usare hardware dedicato).
Inoltre la frequenza di battuta dei tasti e' cosi' blanda che non credo
tolga nulla al processore.
Se ti fai le librerie per la tastiera non le gestisci a interrupt?
E anche se dovessi decuplicare la velocita' di gestione del bios cosa
avresti guadagnato? Anche se dovessi premere 10 tasti al secondo (e vuol
dire che hai il parkinson :-)), in ogni caso occupi una frazione minima del
tempo di calcolo.
Marco

viene bufferizzato solo quando vengono chiamate le funzioni a basso
livello.
Bufferizzare significa entrambe le cose.
Su dispositivi come i dischi (che in genere non ti mandano dati di loro
iniziativa) la bufferizzazione serve a poter trattare i dati da un lato a
blocchi e dall'altro a caratteri.
Sui dispositivi asincroni di ingresso/uscita a carattere (tastiera, seriale,
stampanti) la bufferizzazione serve per evitare di perdere dati, da un lato
o dall'altro.
Marco

 dal bios.
Non credo. Penso piuttosto (sotto DOS) che faccia riferimento all'handle
del file predefinito chiamato CON che il sistema operativo ha collegato
fin dal boot alla tastiera. Il buffer di tastiera invece è gestito
interamente dal BIOS.
EMG

 non l'ho mai digerita (non credo nella portabilità)......
Purtroppo credo che ci sia un trade-off molto delicato tra i due
aspetti. Comunque la portabilità è invece una realtà concreta se non ci
si fossilizza a quella del codice nudo e crudo e si tenta di astrarne un
po' il significato (anche se può sembrare una contraddizione).
EMG

viene bufferizzato solo quando vengono chiamate le funzioni a basso livello.
Esatto.
La prima cosa avviene a livello di sistema ed e' piuttosto
inefficiente.
La seconda a livello di implementazione del linguaggio.
E la cosa, in questo secondo caso, vale sia per l'input che per
l'output.

Marco
Non è vero. Immaginati un gioco arcade in cui i riflessi sono tutto. Devo
aggiornare lo schermo ogni 1/60 di secondo e non posso accettare la lentezza
del'interrupt (ho tante altre cose da gestire oltre alla tastiera).  Al
massimo (è una possibilità) posso installare dei vettori di interrupt che
svolgano i compiti da me richiesti.
Il BIOS è notoriamente lento perchè effettua una miriade di controlli su
ogni dato che riceve. Non utilizzo il BIOS per la tastiera per lo stesso
motivo per cui non utilizzo il BIOS per disegnare a video (lentezza
esasperante). Per delle applicazioni aziendali il BIOS è veloce quanto
basta, ma per quello che devo fare io no (pensa che mi sono dovuto scrivere
delle routine di gestione per molte periferiche, non solo la tastiera).
Ciao, Giuseppe

Marco
Stavo parlando della bufferizzazione specifica del C.
In questo caso il C non perde dati perchč fa uso del buffer di tastiera
gestito dal BIOS (il quale si mantiene sempre aggiornato tramite interrupts)
ma se si limitasse ad ascoltare le porte hardware delle periferiche di input
non si potrebbe considerare piů bufferizzato perchč perderebbe la maggior
parte dei dati.
Un'ultima cosa: a prescindere dal C, non mi risulta che porte come la
parallela siano bufferizzate.
Ciao, Giuseppe

minore velocita'.
Lasciamo perdere il fattore performanza che come hai fatto notare tu dipende
dalle singole implementazioni e parliamo della portabilità.
Che debba esistere un set di funzioni standard capaci di girare sulla
maggior parte delle piattaforme è giusto (anzi è un privilegio che a quanto
so io solo il C ha). Ma che questo set di istruzioni venga considerato come
'un buon metodo di programmazione' o 'buono per raggiungere i propri
obiettivi' non lo accetto affatto. Con quel set di istruzioni si può
scrivere un compilatore, un comando del dos o poco altro, cioè nulla che
abbia un'interfaccia grafica o testuale. Proprio perchè deve essere
portabile lo standard tralascia la maggior parte delle specifiche di una
singola implementazione castrando eccessivamente le possibilità del programm
atore.
Prova tu a scrivere un programma aziendale utilizzando SOLO le funzioni
standard. Impossibile (non puoi farlo certo a riga di comando :-) ).
Secondo me sono passati i tempi in cui andavano per la maggiore il DOS e
l'Unix e scrivendo un prog con quelle istruzioni lo facevi girare su
entrambi. Apri gli occhi e guardati intorno. Sistemi operativi con GUI in
tutte le salse le cui API variano da un giorno all'altro. Lo standard a che
ti serve più. Un programmatore che non inizia a sviluppare per interfacce
testuali come il DOS ma, per esempio, parte da Windows, forse non conoscerà
mai le funzioni standard perchè non gli serviranno a nulla.
Non metto in dubbio comunque che molti di voi trovino molto utile scrivere
con codice portabile in modo da poterlo fare 'funzionare' (che funzioni non
significa che sia da considerarsi buono; metti in conto anche la facilità
d'uso e la gradevolezza dell'interfaccia) su più piattaforme anche per
motivi lavorativi.
Ciao, Giuseppe

EMG
Vale il discorso fatto sopra.
Ciao, Giuseppe

Apri gli occhi e guardati intorno.
E' evidente che il mio parere e' diametralmente opposto al tuo e non
per una semplice questione di opinioni discordanti, ma perche' ritengo
che tu abbia sorvolato molto superficialmente su determinati aspetti.
Innanzitutto chiariamo che lo standard di un linguaggio, quale mezzo
di coordinazione tra gli implementatori e tra i programmatori, deve
esistere per forza di cose.
Nel caso del C e' tale da separare funzioni di ambito generale, senza
alcuna implicazione con la piattaforma di destinazione del programma,
da quelle cosiddette "a basso livello", la cui esistenza e'
altrettanto necessaria, ma che ogni implementatore e' libero di
costruire come vuole.
E' cosi' nel caso di *ogni* standard, non solo del C.
E' per questo motivo che esso non tarpa affatto le ali del
programmatore, ma anzi, la sua esistenza fa si' che si possa
sviluppare attorno al linguaggio proprio quella serie di estensioni
tali, da consentire di interfacciare i programmi col mondo esterno.
Devi tener presente che ci sono piu' modi di programmare.
Esistono progetti in cui lo sviluppo dell'interfaccia con l'utente e'
talmente rilevante da assumere un'importanza maggiore che altri
aspetti (programmazione top-down) ed esistono, invece, progetti, in
cui la definizione dei mezzi di interazione tra programma e utente
viene come ultima (programmazione bottom-up).
Nessuno puo' affermare che per scrivere un programma per una certa
piattaforma bisogna utilizzare SOLO le funzioni standard, ma
sicuramente e' bene separare quelle parti del programma che non hanno
interazione intima con la piattaforma dalle altre.
Lo standard serve appunto a definire quali sono le linee guida da
seguire per rendere il proprio codice quanto piu' portabile possibile.
Il concetto di portabilita', importantissimo nella programmazione, e'
elastico, nel senso che, quante meno sono le modifiche da apporre in
un programma per consentire di essere trasportato da una piattaforma
all'altra, tanto piu' esso e' portabile.
Spesso le modifiche sono per lo piu' destinate alla variazione
dell'interfaccia con l'utente.
Ma ci sono questioni riguardanti la portabilita' per aspetti che
prescindono dalla semplice interfaccia grafica.
Non e' impossibile, ma e' abbastanza difficile, scrivere un programma
di uso commerciale (tanto per definirne la complessita') senza
utilizzare funzioni proprie della piattaforma su cui e' destinato a
girare (ovvero le estensioni a cui facevo riferimento prima).
Ora veniamo al C.
Il C nasce come strumento per lo sviluppo del sistema operativo forse
piu' potente in circolazione.
E' inevitabile che esso sia considerato lo strumento migliore per lo 
sviluppo di programmi di sistema.
Nasce come linguaggio spartano e resta tale.
Spero che nessuno ti obblighi ad usare il C per sviluppare programmi
aziendali, anzi, io ritengo che utilizzare il Clipper o il Cobol o il
Visual Basic sia molto piu' comodo, per le facilita' offerte nella
gestione dei dati.
In ultimo considera il fatto che il codice "buono" non e' quello che
appare e che si accattiva gli occhi, ma quello che *funziona
correttamente*.
Lo stesso principio vale per i sistemi operativi.
I sistemi GUI (leggasi Windows9x) saranno anche "piu' belli" e piu'
facili da utilizzare, ma se devono impiantarsi ogni tre secondi (che
per me significa *non funzionare*), preferisco ricorrere ad un sistema
operativo come Unix, che non e' affatto passato di moda, senza
finestre, ne' fronzoli, ma solido come e' indispensabile che un
sistema operativo sia.

parallela siano bufferizzate.
No, infatti. A quanto ne so c'e' un solo registro che fa da "buffer", e per
gestire a mano la parallela bisogna implementare qualche meccanismo di
handshake.
Marco

delle routine di gestione per molte periferiche, non solo la tastiera).
Un momento: E' ovvio che, da qualche parte nel codice, ci sara' una
istruzione del tipo leggi_tastiera.
Ora, se questa funzione la implementi tu andando a leggere istantaneamente
le porte del controllore (che non mi ricordo come si chiama) hai ottime
probabilita' di perdere i dati a meno che il tasto premuto non rimanga
memorizzato da qualche parte (buffer. E mi pare che lo sia). Questo implica
che comunque da qualche parte deve esserci il gestore di interruzione per la
tastiera, e se non usi quello del BIOS devi scriverlo tu.
Non ricordo esattamente come funziona il controllore di tastiera, ma mi pare
che esso comunque generi una interruzione, che serve se non altro a
segnalare al gestore la disponibilita' di un dato affinche' questi segnali
al controllore l'avvenuta ricezione (handshake), oltre che a bufferizzare il
dato letto.
Se leggi_tastiera invece usa, ad esempio, la funzione 1 dell'int16h essa fa
comunque un polling, ma lo fa sul dato gia' bufferizzato. La differenza di
velocita' nei due casi e' davvero infima, tenuto conto della frequenza con
la quale ciene premuto un tasto sulla tastiera.
Per l'int10h hai ragione, sopratutto quando si parla di grafica. Ma sulla
tastiera non credo che si perda tanto tempo: comunque devi usare un gestore
di interruzione.
Se invece di usare una funzione del tipo leggi_tastiera demandi la gestione
dell'input proprio al gestore di interruzione dedicato guadagni sicuramente
molto in velocita' per il semplice fatto che NEL CODICE non devi andare a
fare il polling, ma in questo caso oltre che a riscriverti del tutto il
gestore devi preoccuparti anche di mille altri dettagli. Forse e' questo
quello che intendevi.
Marco

interamente dal BIOS.
Puo' darsi, anzi probabilmente e' cosi' per stdin. Stavo pensando a getch
del turboc.. :)
Marco

 bufferizzato SOLO perchè si appoggia al BIOS, altrimenti....
No, continui a confondere i due livelli, completamente diversi, di
bufferizzazione. L'I/O del C è bufferizzato indipendentemente da quello
che c'è sotto (potrebbe esserci anche un'omino che digita a mano i dati
che ti servono). Bufferizzato, nel caso del C, significa (ad esempio nel
caso del DOS) che la lettura dal file CON avviene non carattere per
carattere ma a blocchi. E' indifferente chi è che fornisce tali blocchi.
Sarà il BIOS con la sua ISR (Interrupt Service Routine) ma questo non
rientra in ciò che il C e i programmatori C devono sapere.
EMG

...

Ciò che dici tu non fa un piega: lo ritengo giustissimo. Voglio però farti
capire che quelle funzioni che fanno parte dello standard sono si supportate
(riesci a fare girare il programma), ma non servono piu nei sistemi
operativi moderni che utilizzano delle complesse GUI (non prendere ad
esempio solo win: anche nel terzo mondo sanno che è una fetecchia....) come
Linux, MacOS, ecc...

EMG
Ma a blocchi solo per determinate istruzioni. Mi riferisco a getchar (che
prima della spiegazione di Laforgia neanche conoscevo non avendola mai
usata). Provando con getch (o con altre funzioni) io questa bufferizzazione
ad alto livello non la vedo.....
Prova a farmi un esempio che forse mi convinco....
Grazie per le risposte
Ciao, Giuseppe

...

Mi sono accorto di aver generalizzato sulla lentezza del BIOS nel mio post
precedente. Ho fatto dei test di velocità è il BIOS non è poi così lento
nella gestione della tastiera (certo non si può dire però che sia
ottimizzato per i miei scopi...).
Nulla toglie però che alcune operazioni possono essere velocizzate anche
solo con la lettura diretta in memoria del buffer di tastiera. Ho fatto un
pò di calcoli e sono arrivato alla conclusione che effettuare il polling
della porta della tastiera mi comporterebbe del lavoro superfluo. Potrei
installare dei vettori temporanei di interrupt e gestire da lì la cosa....


operativi moderni che utilizzano delle complesse GUI
Non sono d'accordo.
Una parte del programma e' destinata a gestire l'interfaccia.
L'altra (la piu' importante) e' quella di elaborazione per la quale le
routine standard sono le uniche realmente necessarie.

ad alto livello non la vedo.....
Ovvio, perche' getch() e' a basso livello.

 ad alto livello non la vedo.....
Per forza. La funzione getch() non è standard e quindi il discorso che
ti ho fatto potrebbe non applicarsi.
EMG

Ovvio, perche' getch() e' a basso livello.
Allora è tutto OK. Se la bufferizzazione è solo quella che ho visto con
getchar allora ho capito il funzionamento.
Grazie a tutti.
Ciao, Giuseppe

routine standard sono le uniche realmente necessarie.
Prendo come esempio Win perchè lo conosco: solo le funzioni matematiche
possono risultare necessarie. Tutte le altre sono state ridefinite (anche
allocazione memoria). Le funzioni standard possono essere utilizzate ma non
sfruttano le potenzialità del win.
Comunque ti ribadisco il mio pensiero: benchè io non lo farei, considero una
buona tecnica quella di utilizzare le funzioni standard per il corpo del
programma.
Ciao, Giuseppe

getchar allora ho capito il funzionamento.
Per darti un'idea di cosa si intende realmente per bufferizzazione in
C osserva una porzione della libreria stdio.h fornita con il Borland
C++ 5.02 :
/* Definition of the control structure for streams
*/
typedef struct  {
        unsigned char  *curp;       /* Current active pointer     */
        unsigned char  *buffer;     /* Data transfer buffer       */
        int             level;      /* fill/empty level of buffer */
        int             bsize;      /* Buffer size                */
        unsigned short  istemp;     /* Temporary file indicator   */
        unsigned short  flags;      /* File status flags          */
        wchar_t         hold;       /* Ungetc char if no buffer   */
        char            fd;         /* File descriptor            */
        unsigned char   token;      /* Used for validity checking */
}       FILE;                       /* This is the FILE object    */
.
.
.
extern  FILE        _RTLENTRY _EXPDATA _streams[];
.
.
.
#define stdin   (&_streams[0])
#define stdout  (&_streams[1])
#define stderr  (&_streams[2])
.
.
.
int      _RTLENTRY _EXPFUNC _fgetc(FILE * __stream);           
/* used by getc() macro */
int      _RTLENTRY _EXPFUNC _fputc(char __c, FILE * __stream); 
/* used by putc() macro */
.
.
.
#define getc(f) \
  ((--((f)->level) >= 0) ? (unsigned char)(*(f)->curp++) : \
    _fgetc (f))
#define putc(c,f) \
  ((++((f)->level) < 0) ? (unsigned char)(*(f)->curp++=(c)) : \
    _fputc ((c),f))
#define getchar()   getc(stdin)
#define putchar(c)  putc((c), stdout)
Osserva, in particolare, come sono definiti getc() e putc()...

programma.
Non lo faresti nella programmazione per Windows, ma magari per altri
sistemi operativi non hai alcun problema...

sistemi operativi non hai alcun problema...
Anche in DOS non lo faccio. Mi secca dover limitare i miei programmi alla
sola riga di comando, soprattutto quando sono troppo complessi. Mi piacciono
le interfacce multicolori e piacevoli alla vista: se vedessi i miei listati
sono tutti un susseguirsi di funzioni della libreria conio.h. A volte,
quando non vi è necessità di accesso ai file, stdio.h neanche mi serve.....
Ciao, Giuseppe

L'input ad alto livello nel C viene gestito come un FILE, cioč una sequenza
di dati memorizzata in un buffer (e da qui l'aggetivo di input
bufferizzato). Di come poi vengano forniti i dati a questo file si occupano
le funzioni a basso livello che variano da implementazione a
implementazione. In teoria potrebbero appoggiarsi ai servizi del BIOS o al
buffer di tastiera ma questa non č una cosa che interessa al programmatore.
E' giusta questa mia definizione? Ho afferrato il concetto?
Grazie delle risposte, Giuseppe

quando non vi è necessità di accesso ai file, stdio.h neanche mi serve.....
...questo non significa che tutti i programmi siano solo orientati
all'interfaccia...


Mi sembra perfetta.
EMG

Al mondo non esiste solo Windows.
Ho preso Windows solo come esempio (ho già detto che non lo ritengo nè un
buon SO nè l'unico in commercio). Il mio concetto vale per tutte gli altri
sistemi operativi che operano o a 32 bit o che hanno un'interfaccia grafica.
Ciao, Giuseppe

Mi sembra perfetta.
Bene allora, ho colmato il mio dubbio.
Grazie a tutti per le risposte.
Ciao, Giuseppe