Newsgroup: it.comp.lang.c
Titolo: Una piccola curiosità...

Ciao,
solo una domanda-lampo: il return 0 nel main č facoltativo ma, quando lo 
si mette, perché non si usa invece EXIT_SUCCESS, che in teoria sarebbe 
la soluzione piů portabile?
--
We've all heard that a million monkeys banging on a million typewriters
will eventually reproduce the entire works of Shakespeare. Now, thanks
to the Internet, we know this is not true.      -- Robert Silensky
~> 
http://scriverefantascienza.blogspot.com/

 la soluzione più portabile?
Vero, tu usa quelle costanti, così se il tuo codice girerà su VMS non
avrà problemi..poi
non vedo perchè scrivere codice portabile se non deve girare su altri
ambienti..
Salut.

 ambienti..
Perché non costa niente scrivere codice portabile ed è il modo corretto di
programmare. Come regola generale di programmazione, è sempre bene
astrarre il più possibile dalle piattaforme di sviluppo.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 astrarre il più possibile dalle piattaforme di sviluppo.
Concordo in pieno, anche sulla *regola generale*.
Poi ovviamente la portabilità costa più o meno in base al singolo
caso, io la valuto in analisi.
Salut.

 astrarre il più possibile dalle piattaforme di sviluppo.
Dunque sarebbe effettivamente meglio usare EXIT_SUCCESS ed EXIT_FAILURE? 
Un'altra cosa che non mi ero mai chiesto prima è: come faccio a 
controllare il valore restituito dal main(), e quando serve farlo? Su 
GNU/Linux, ad esempio, mi verrebbe quasi da pensare che quando chiamo il 
programma da shell potrei fare una vera e propria assegnazione... è così?
ciau


 programma da shell potrei fare una vera e propria assegnazione... è così?
In ambiente di shell unix puoi usare la variabile speciale $? che 
riporta il valore riportato dall'ultimo programma eseguito. 
Nell'ambiente delle shell di Windows puoi testare il valore ritornato 
da 'errorlevel'.
All'interno di un programma C esistono funzioni di libreria che 
possono ritornare lo stato di uscita di un programma figlio.
Ciao
Giovanni
-- 
   A computer is like an air conditioner,
   it stops working when you open Windows.
   Registered Linux user #337974  < 
http://giovanni.homelinux.net/
 >

controllare il valore restituito dal main(), e quando serve farlo? 
Serve a chi lancia il processo. Normalmente a uno script batch in modo
da compiere operazioni specifiche in base al codice d'uscita del
programma. Per esempio, ai tempi del DOS esisteva un comando esterno
CHOICE che serviva a implementare un menu tipico (premi 1 per, premi 2
per...). L'esame del codice di ritorno e quindi l'operazione specifica
da compiere si basava sul controllo della variabile ERRORLEVEL del
sistema operativo.

 Dunque sarebbe effettivamente meglio usare EXIT_SUCCESS ed EXIT_FAILURE? 
A stretto rigore è  vero e  le considerazioni di Andrea sono pienamente 
condivisibili.
Va anche detto però che in tutto lo standard non c'e' un solo esempio in 
cui si usi return EXIT_SUCCESS  e invece compare return 0.
Il mio punto di vista è  che il C,  come e più di altri linguaggi, 
fornisce uno  scheletro sintatico  ridondante che permette di accomodare 
diversi stili di programmazione:  da quelli più 
implementazione-dipendenti a  quelli più  astratti  con tutte le 
tonalità di grigio in mezzo. Ci possono essere buone ragioni per 
qualsiasi scelta in questa gamma.
Giorgio

 cui si usi return EXIT_SUCCESS  e invece compare return 0.
Perché è invalso che EXIT_SUCCESS equivalga a 0, ma è sempre bene usare la
costante simbolica, più che quella letterale. Non vedo situazioni in cui
sia ragionevole fare il contrario, a meno che il sistema non supporti la
costante simbolica (e in tal caso procederei a definirla e poi usarla). Le
"tonalità di grigio" non sono accettabili se si scrive codice portabile e
scrivere codice portabile, specialmente laddove non si intenda
trasportabile completamente ma riadattabile con poco sforzo, è la regola
base della programmazione in linguaggi, come C e C++, ideati per
funzionare su un insieme molto eterogeneo di piattaforme.


 cui si usi return EXIT_SUCCESS  e invece compare return 0.
Evidentemente non hai mai scritto codice C per un sistema Digital VAX/VMS.
#if defined VAXC || defined __DECC
#undef EXIT_SUCCESS
#undef EXIT_FAILURE
#define EXIT_SUCCESS	1	   /* Return code for NO ERRORS*/
#define EXIT_REMARK	0x0801800B /* Return code for REMARKS  */
#define EXIT_WARNING	0x08018010 /* Return code for WARNINGS */
#define EXIT_ERROR	0x0801801A /* Return code for ERRORS   */
#define EXIT_FAILURE	0x08018022 /* Return code for ERRORS   */
#define SYSINCLUDE	getenv("INCLUDE")	/* "SYS$LIBRARY" */
#endif



Ad ogni modo è facoltativo solo con i compilatori c99, se non lo
specifichi il valore di ritorno è indefinito.

 Evidentemente non hai mai scritto codice C per un sistema Digital VAX/VMS.
...
Mi sembrava di averlo scritto a chiare lettere e, viste le risposte, lo 
ripeto: le considerazioni di Andrea sono pienamente condivisibili.
Il punto che volevo fare è  che (per necessità  o per fortuna a seconda 
dei punti di vista) il linguaggio non obbliga certe scelte  che quindi 
sono responsabilità  del programmatore. Questi ha completa libertà 
(indiendentemente dai gusti miei,  di Laforgia o  di chiunque altro) di 
fare delle scelte che potrebbero,  in determinate circostenza,  essere 
giustificabili. Questo  è  tutto. Se poi uno vuole fare il paladino 
dell'  astrazione  sempre e comunque,  di nuovo no problem.  Mi limitavo 
a segnalare che lo standard,  che ha sicuramente molte pecche,  ma forse 
non è  scritto da niubbi alle prime armi,  non riporta negli esempi l' 
uso (consigliabile)  di EXIT_SUCCESS  ma di 0. Giusto come testimonianza 
di un uso frequente.
Altrimenti poi si finisce per scrivere del codice bellissimo ma di non 
comprendere più  quello scritto dagli altri :-(
Giorgio

 Giovanni
Sono fatti del VAX da notte, che tra l'altro rappresenta solo una 
nicchia, essendo estinto :-)
In generale pero', ed esite una tonnellata di codice scritto cosi', il 
valore 0 e'
*convenzionalmente* utilizzato da sempre come OK.
Attenersi a comportamenti *educati* aiuta, ma poi dipende dalla 
specifica applicazione.
Se ci si trova, ad esempio, a mettere le mani in codice gia' esistente, 
e' bene attenersi alle
regole di quel codice, per evitare di introdurre problemi!!!
A volte le buone intenzioni hanno risultati catastrofici.
brix

 nicchia, essendo estinto :-)
L'esempio vale come regola generale e conferma che è bene attenersi alle
convenzioni standard. Non c'è motivo per non farlo.


 di un uso frequente.
Lo standard è quello che ha introdotto EXIT_SUCCESS, è questo il punto.
Che poi gli esempi siano fatti con 0 non aggiunge nulla al discorso di
base.


   
Appunto. mentre 0 *è sempre* OK, EXIT_SUXCCESS è *sempre* implementation 
dependent
(vedi sotto) per cui, se in generale è bello attenersi agli standard, 
nel particolare ci sono dei casi
in cui è sempre *meglio* utilizzare il valore che *sempre* e' 
interpretato nel modo voluto.
Tanto per fare un esempio, quando è necessario convire con applicazioni 
anche un po'
datate (purtroppo capita!). Se cambio un programma che puo' essere 
richiamato da una
applicazione che si aspetta lo 0 come ritorno, se il mio sistema (VAX 
tanto per rifarci all esempio)
si e' definito l' EXIT_SUCCESS con valore arbitrario !=0, ritornare 
EXIT_SUCCESS significa
fare fallire l' applicazione, di cui magari non ho il controllo....e 
farsi del male.
Oltretutto lo standard dichiara esplicitamente che 0 == OK, per cui non 
solo NON
si viola nessuna buona pratica di programmazione, ma ci si pone al 
riparo delle "implementation
dependent" anche per i casi particolari...
"Finally, control is returned to the host environment. If the value of 
status is zero or
EXIT_SUCCESS, an *implementation-defined* form of the status successful 
termination is
returned. If the value of status is EXIT_FAILURE, an 
implementation-defined form
of the status unsuccessful termination is returned. Otherwise the status 
returned is
implementation-defined."
Dove la parola chiave è: "if the value of status is zero *OR* 
EXIT_SUCCESS"...
brix

 interpretato nel modo voluto.
Assolutamente no. Non puoi essere sicuro che 0 venga *sempre* interpretato
nel modo voluto e ne è testimonianza la piattaforma citata in precedenza.
D'altdonde, chi mi vieta di costruire una piattaforma su cui il valore di
successo di uscita di un processo è 987234? Su una piattaforma su cui è
definito EXIT_SUCCESS, il valore assunto dalla costante è quello di
successo su quella piattaforma (0 laddove sia 0, 1 laddove sia 1, 987234
laddove sia 987234). Non è *mai* meglio utilizzare una costante letterale,
laddove la piattaforma definisca una costante simbolica preposta a
rappresentare lo stesso valore logico. Anche quando il successo, su una
piattaforma, è identificato da zero *o* EXIT_SUCCESS, è *sempre* meglio
utilizzare EXIT_SUCCESS, perché il giorno che si trasporterà quel codice
su un'altra piattaforma, EXIT_SUCCESS porterà correttamente il valore
logico di successo. Il rischio di usare la costante letterale è che su
un'altra piattaforma lo 0 non rappresenti il successo.


Andrea Laforgia ha scritto:

No assolutamente no :-)
Lo 0 è uno *standard* da prima dell' introduzione dell' EXIT_SUCCESS ...
come ribadisce anche lo standard ultimo (C99), rileggilo pure :-)
Dove la parola chiave è: "if the value of status is zero *OR* 
EXIT_SUCCESS"...
Mi sembra chiaro , no? l' OR non lascia dubbi...e lo *zero* viene prima.
Infatti su tutti i sistemi 0 è preso per OK, sempre (OR)... pure sul VAX 
e prima anche sul PDP1,
se e' per questo. Se lo 0 ti fa proprio skifo, ridefiniscilo pure ..
#define EXIT_SUCCESS_CLASSIC    0
Ma il discorso generale non era proprio quello, rileggi... un po di 
latenza ?
brix

 e prima anche sul PDP1,
Niente affatto! I sistemi sono liberi di interpretare qualsiasi valore
come valore di successo e ci mancherebbe pure!. Vorrei vedere pure che lo
standard di un linguaggio imponesse limiti allo sviluppo di una
piattaforma!. Ogni sistema è libero di stabilire quale sia il valore per
il successo di un processo. E' quindi sempre bene usare EXIT_SUCCESS, per
sicurezza. D'altronde, sta lì apposta per quello.


 sicurezza. D'altronde, sta lì apposta per quello.
Non e' quello che dice lo standard, che dice che "return 0" deve aver lo 
stesso effetto di "return EXIT_SUCCESS". Ci sara' di mezzo qualche 
compiler-magic che trasforma lo 0 nel codice nel valore corretto (un po' 
come usare 0 per il puntatore nullo)
ciao
Giacomo

"valore standard".
Abbiamo perso il filo del discorso. E' un valore standard, ma non č
*IL* metodo standard. Stiamo parlando di cose diverse. Lo standard
contempla benissimo i casi in cui non si usi return 0 ma si usi return
EXIT_SUCCESS. Quello di cui stiamo discutendo č se sia meglio, in
taluni casi, usare "return 0" al posto di "return EXIT_SUCCESS" e non
č cosě, *mai*. A mio parere, ovviamente. Il fatto che "return 0"
generi lo stesso effetto di "return EXIT_SUCCESS" č purtroppo una
forzatura che č stata esercitata sullo standard, visto che lo 0 č
invalso come codice positivo di ritorno.

 #define EXIT_SUCCESS    1       /* Return code for NO ERRORS*/
Vuoi dire che la libreria su VMS non definisce correttamente 
EXIT_SUCCESS? Allora a cosa caspita serve utilizzare questa costante?
Oppure quello che riporti e' proprio uno header della libreria standard?
E.

   
Quello di cui si sta' discutendo pare religione e non programmazione: lo 
standard
parla chiaro, poi uno fa quelle che meglio crede.
bye
brix

Tra l' altro e qui chiudo, il C99 specifica a *chiare-lettere* che il 
main ritorna
automaticamente 0 se non viene specificato nulla, non EXIT_SUCCESS!
Ora questo NON e' un caso, infatti lo 0 non se lo sono inventato 
perche'  gli giravano
le palle, ma perche' lo 0 e' l' unico valore *univoco* interpretato 
sempre allo stesso
modo sulle CPU bagonghi e sui sistemi triccheballache, per cui, a 
rigore, se si desidera
fare un software *veramente* portabile e che giri sempre su ogni 
ambiente, dal piu'
recente al piu' arcaico, dagli embedded alle sofisticherie, lo 0 e' a 
rigore di termini,
la scelta migliore.
Cito lo standard:
If the return type of the main function is a type compatible with int, a 
return from the
initial call to the main function is equivalent to calling the exit 
function with the value
returned by the main function as its argument;10) reaching the } that 
terminates the
main function returns a value of 0.
brix

 #define EXIT_SUCCESS_CLASSIC    0
PS per la prima volta mi trovo ad approvare ciò che afferma Andrea :-)
    Mai usare le costanti scritte direttamente in un programma.


 IMO non vuole certamente dire quello sh sostieni tu.
Ma va! Vuol dire che 0 e' *SEMPRE* OK, e poi, se qualche esoterico sistema
si definisce un EXIT_SUCCESS == pippo , quel sistema e solo lui dovra' 
prendersi
la briga di interpletarlo come OK, OLTRE allo 0 :-)

Rispondi deove aver letto tutto il thred, please.
Brix


Non è l'header standard ma di un mio programma. Non ricordo come 
fossero definiti nell'header di sistema ma ricordo la necessità di 
usare delle strutture ben precise per linkare i messaggi all'eseguibile
Il SO VAX/VMS ed il successivo che girava su ALPHA in realtà usavano i 
codici seguenti. Solo i due bit meno significativi vengono 
interpretati dal SO.  Gli altri bit puntano a delle stringe per 
riportare al terminale un messaggio.
#define EXIT_SUCCESS    1       /* Return code for NO ERRORS*/
#define EXIT_REMARK    0x0801800B /* Return code for REMARKS  */
#define EXIT_WARNING    0x08018010 /* Return code for WARNINGS */
#define EXIT_ERROR    0x0801801A /* Return code for ERRORS   */
#define EXIT_FAILURE    0x08018022 /* Return code for ERRORS   */
Per i 2 bit -significativi:
1 = 0k e nessun messaggio
2 = errore
3 = messaggio informativo
0 = warning
In mancanza del puntatore alla stringa veniva proposto un messaggio 
standard (eccetto per 1 = OK)


 la briga di interpletarlo come OK, OLTRE allo 0 :-)
Forse il mio inglese è un po' arrugginito ma mai ho sentito una 
interpretazione simile alla tua ne lo avrei mai tradotto come fai tu.


Giovanni ha scritto:

Quale interpretazione ??????????? Facciamo a non capirsi  ??????????? Lo 
statement e' chiarissimo!
"if the value of status is zero *OR* EXIT_FAILURE, *an* 
*implementation-defined* *form* .... "
"Se il valore di status e'  zero *O* (oppure) EXIT_FAILURE, una forma 
dipendendente dall' implementazione, ...........
Mi piacerebbe proprio sapere in che altro modo tradurresti questa frase!!!
E se lo scrivi, fai anche il piacere di *dettagliare*
brix

 E se lo scrivi, fai anche il piacere di *dettagliare*
Se il valore di status è 0 od altro valore definito 
dall'implementazione ......
Ora puoi dare una tua diversa interpretazione ma quello zero non 
significa che è sempre da considerarsi OK.  Il VAX/VMS uno zero lo 
interpreta come warning!  Se proprio volessimo togliere il pelo 
dall'uovo direi che 0 ed ogni altro valore vanno bene per EXIT_SUCCESS 
e qualsiasi valore != 0 per EXIT_FAILURE.   IMO, anche se non ho mai 
partecipato alla definizione del C, quella è la richiesta di qualche 
partecipante/membro che siccome aveva sempre usato 0 ha preteso che 
rimanesse nel testo.
PS:  Ma sei uno degli estensori dello standard?  Mi stai riportando 
alle discussioni filosofiche dei tempi in cui partecipavo alle 
riunioni degli standard per il CHILL.  Che fatica capirsi con 
l'inglese quando parlavano i cinesi od i finlandesi ;-)


 l'inglese quando parlavano i cinesi od i finlandesi ;-)
No.  lavori in Siemens-Nokia ???? in genere con i Finlandesi ci si 
capisce benissimo ... con cinesi nun zo.
ciao,
brix

 No.  lavori in Siemens-Nokia ???? 
Ora non più.


Ma se la libreria standard del VMS definiva
 > #define EXIT_SUCCESS    1       /* Return code for NO ERRORS*/
perché nei tuoi programmi inserisci queste righe?
 >>> #if defined VAXC || defined __DECC
 >>> #undef EXIT_SUCCESS
 >>> #define EXIT_SUCCESS    1       /* Return code for NO ERRORS*/
E.

 Ora non più.
Meglio.
brix

 Meglio.
Il tempo passa.  Arriva anche il tempo di andare in pensione :-)



Francamente non ricordo cosa la libreria definisse EXIT_SUCCESS ma il 
programma girava su DOS 6.2 - WINDOWS 95 - SUN - Linux - Minix - 
VAX/VMS e DEC-alpha.
La #undef dei valori di uscita OK (forse?) la ho messa solo per 
documentare i valori diversi da tutti gli altri SO o (forse?) per 
eliminare il messaggio di default.  Sicuramente la #undef di 
EXIT_FAILURE era necessaria per poter ridefinire i messaggio di uscita.



Fortunello ;-)

 compilatore ne dalle librerie ma dal sistema operativo!
Pero' le librerie possono modificare l'interazione tra l'OS e il codice 
C. Per esempio le librerie del gcc per Windows interpretano gli * e ? 
negli argomenti passati al main e fanno le sostituzioni che in un 
ambiente *nix avrebbe fatto la shell.
E.

 punto di vista non lo era......
Quello che usavo io non era sicuramente C99 visto che sto palando di 
almeno 10 anni fa, ma solo C90.  In ogni caso quella frase che tu hai 
più volte citato era riportata pari pari anche nello standard 
precedente (7.10.4.3).
Ho l'impressione che sei l'unico a dare una simile interpretazione 
visto che, dopo un po' di ricerche in rete, non ho trovato una 
libreria che si comporti come tu stai ipotizzando.  Per quanto ho 
visto tutte ritornano il valore di status al kernel (o al gestore 
della memoria) senza alcuna manipolazione.


 ambiente *nix avrebbe fatto la shell.
Sicuramente la libreria modifica i path dei filename scritti in 
modalità unix con '/' nella modalità DOS, cioè '\'
Quanto ai caratteri jolly ne sei proprio sicuro?  Guarda cje anche su 
windows la shell espande * e ? allo stesso modo di unix.


 windows la shell espande * e ? allo stesso modo di unix.
No, non lo fa. Sono i programmi a farlo. Prova a dare il comando:
echo *
E.