È necessario seguire lo standard, prendere lo standard C per quella materia?


17

Ci sono persone molto esperte su Stack Overflow che parlano sempre dello standard C. Le persone non sembrano apprezzare le soluzioni non portatili, anche se lavorano per me. Ok, capisco che lo standard deve essere seguito, ma non pone ostacoli alla creatività del programmatore?

Quali sono i vantaggi concreti che derivano dal seguire uno standard? Soprattutto perché i compilatori possono implementare lo standard in modo leggermente diverso.


7
Potresti chiarire cosa intendi con "lo standard"? Vuoi dire non reagire su un comportamento che non è definito dalla norma? O non usi le funzionalità estensioni / compilatore? O convenzioni di stile?
ikh,

1
@ikh Sta adottando gli standard ISO C (C90, C99, C11).
Aseem Bansal,

9
È lo stesso che dire che scrivere o parlare in inglese, usando la grammatica e il vocabolario inglese, mette le catene sulla tua creatività. Certo, le persone possono fare cose meravigliose infrangendo le regole, a scapito della coerenza, ma puoi scrivere milioni di libri creativi pur aderendo allo "standard" dell'inglese.
Avner Shahar-Kashtan,

puoi aggiungere un esempio di "Le persone sembrano non apprezzare le soluzioni non portatili, anche se funzionano per me"?
BЈовић,

1
@PHIfounder Solo per affrontare l'ultimo caso, puoi omettere il ritorno dal main, è implicitamente return 0 :)
Daniel Gratzer

Risposte:


45

Ci sono alcuni motivi per cui attenersi allo standard è una buona cosa.

  1. Essere bloccati in un compilatore fa schifo. Sei completamente in balia di un gruppo di sviluppatori con la loro agenda. Ovviamente non sono pronti a prenderti o altro, ma se il tuo compilatore inizia a rallentare ottimizzazioni, nuove funzionalità, correzioni di sicurezza ecc., Peccato; Sei bloccato. In casi estremi alcune aziende devono iniziare a rattoppare qualsiasi strumento da cui si siano resi dipendenti. Questo è un enorme spreco di tempo e denaro quando ci sono altri strumenti di lavoro là fuori.

  2. Essere bloccati in una piattaforma fa più schifo. Se stai spingendo software su Linux e vuoi passare a Windows perché ti rendi conto che il tuo mercato è davvero lì, avrai un sacco di tempo a cambiare ogni hack non portatile che hai nel tuo codice per giocare bene con GCC e MSVC. Se hai diversi pezzi del tuo core design basati su qualcosa del genere, buona fortuna!

  3. Le modifiche incompatibili all'indietro fanno schifo più duro. Lo standard non romperà mai il tuo codice (Ignora python). Alcuni autori di compilatori casuali potrebbero decidere che in realtà questo componente aggiuntivo specifico per l'implementazione non vale la pena e rilasciarlo. Se ti capita di fare affidamento su di esso, allora sei bloccato su qualsiasi versione obsoleta precedente era l'ultima.

Quindi il messaggio prioritario qui, attenersi allo standard ti rende più flessibile . Hai sicuramente un linguaggio più limitato, ma ne hai di più

  • biblioteche
  • Supporto (le persone conoscono lo standard, non tutti gli intricati hack specifici del compilatore)
  • Piattaforme disponibili
  • Strumenti maturi
  • Sicurezza (sicurezza futura)

È un equilibrio delicato, ma ignorare completamente lo standard è sicuramente un errore. Tendo a organizzare il mio codice C in modo da fare affidamento su astrazioni che potrebbero essere implementate in modo non portatile, ma che posso effettuare il port in modo trasparente senza modificare tutto ciò che dipende dall'astrazione.


+1 abbastanza giusto :), grazie ... Ero seriamente confuso dal modo in cui i compilatori si discostavano leggermente dagli standard e mi facevano sentire scettico nel seguirlo rigorosamente, avevo bisogno di conoscerne i pro e i contro e tu li hai identificati chiaramente.
decimale0

6
Probabilmente anche un comportamento indefinito fa schifo. Con c è abbastanza facile avventurarsi in UB se non si segue da vicino lo standard.
Codici A Caos il

@CodesInChaos D'accordo, il comportamento indefinito è ottimo da un lato poiché consente alcune ottimizzazioni pazze, ma dall'altro il debug ...
Daniel Gratzer

6

Lo standard è una sorta di "contratto" tra te e il tuo compilatore che definisce il significato dei tuoi programmi. Come programmatori, abbiamo spesso un certo modello mentale di come funziona la lingua, e questo modello mentale è spesso in contrasto con lo standard. (Ad esempio, i programmatori C spesso considerano un puntatore approssimativamente "un numero intero che indica un indirizzo di memoria", e quindi assumono che sia sicuro eseguire qualsiasi aritmetica / conversione / manipolazione su puntatori che si potrebbe eseguire con un numero intero che denota una memoria indirizzo. Questo presupposto non concorda con lo standard; in realtà impone restrizioni molto rigide su ciò che è possibile fare con i puntatori.)

Quindi, qual è il vantaggio di seguire lo standard, piuttosto che il tuo modello mentale?

In poche parole, è che lo standard è corretto e il tuo modello mentale è sbagliato. Il tuo modello mentale è in genere una visione semplificata di come funzionano le cose sul tuo sistema, in casi comuni, con tutte le ottimizzazioni del compilatore disabilitate; i produttori di compilatori generalmente non si sforzano di conformarsi ad esso, soprattutto quando si tratta di ottimizzazioni. (Se non mantieni la fine del contratto, non puoi aspettarti un comportamento specifico dal compilatore: garbage in, garbage out.)

Le persone non sembrano apprezzare le soluzioni non portatili, anche se lavorano per me.

Potrebbe essere meglio dire "anche se sembrano funzionare per me". A meno che il compilatore non specifichi specificamente che un determinato comportamento funzionerà (vale a dire: a meno che tu non stia utilizzando uno standard arricchito, costituito dalla documentazione standard più corretta del compilatore), non sai che funziona davvero o che è davvero affidabile. Ad esempio, l'overflow di numeri interi con segno di solito comporta il wrapping su molti sistemi (quindi INT_MAX+1è in genere INT_MIN) - tranne che i compilatori "sanno" che l'aritmetica di numeri interi con segno non trabocca mai in un programma C (corretto) e spesso eseguono ottimizzazioni sorprendenti basate su questo " conoscenza".


1
Potresti compilare -fwrapv, e quindi stai usando un linguaggio leggermente diverso, non standard in cui l'aritmetica intera con segno si avvolge sempre.
user253751

@immibis: Quando è stato scritto C89, secondo il suo documento di logica, la maggior parte dei compilatori contemporanei ha definito la semantica di wrapping silenzioso per l'overflow di numeri interi. In molti casi, avere un certo tipo di garanzie su ciò che accade in caso di overflow di numeri interi può consentire al codice di essere più efficiente di quanto sarebbe possibile senza tali garanzie, soprattutto se le garanzie non arrivano al punto di imporre un comportamento di wrapping preciso [preciso il comportamento di wrapping potrebbe essere emulato utilizzando matematica non firmata, ma la semantica più libera ma comunque adeguata a soddisfare i requisiti può consentire un codice più efficiente].
supercat

@immibis: Peccato che i revisionisti siano stati in grado di convincere le persone che comportamenti attuati quasi all'unanimità tra i compilatori per determinate piattaforme (o in alcuni casi al 100% all'unanimità) non sono mai stati "standard" su tali piattaforme, poiché in molti casi il la perdita di efficienza derivante dalla necessità di evitare tali comportamenti non sarà recuperata dalle "ottimizzazioni" che un compilatore è stato in grado di raggiungere revocandole.
supercat,

4

Capisco che lo standard deve essere seguito, ma non pone ostacoli alla creatività del programmatore? ci sono ancora alcune differenze nel modo in cui diversi compilatori seguono gli standard. Ad esempio, posso scrivere un codice che funzioni, molto buono in termini di prestazioni e velocità, vale a dire tutto ciò che conta, ma che potrebbe non necessariamente seguire rigorosamente gli standard.

No. Lo standard dice cosa è permesso fare. Se non viene specificato, ci si trova in un territorio di comportamento indefinito e quindi tutte le scommesse sono disattivate: il programma è libero di fare qualsiasi cosa.


Dato che hai citato un esempio specifico di void main()vs int main(), posso migliorare la mia risposta.

void main()non è una dichiarazione standard della funzione principale. Può funzionare su alcuni compilatori tramite estensioni, ma si basa sull'implementazione. Anche se funziona, devi controllare se fa quello che vuoi. Il problema è che gli sviluppatori di compilatori potrebbero decidere di rimuovere void main()con la prossima versione del compilatore, rompendo l'applicazione.

D'altra parte, lo standard definisce chiaramente la firma di main as int main()e dice cosa dovrebbe fare.


D'altra parte, ci sono cose non definite nello standard. Quindi, potrebbe essere applicato un altro standard (come ad esempio POSIX). L'esempio migliore potrebbe essere con l'implementazione dei thread in c ++ 03, poiché i programmi standard c ++ 03 erano a 1 thread. In tal caso, sei costretto a utilizzare la libreria dipendente dalla piattaforma o qualcosa di simile a boost .


4
Tutto ciò che fa un compilatore che non è standard non è un comportamento indefinito, le estensioni del compilatore sono ben definite nel senso che sono deterministiche e intenzionali. UB no.
Daniel Gratzer,

@jozefg Il modo in cui è stato chiesto - è ovvio che l'OP ha pensato al modo di implementare UB. Ad esempio, i thread non sono stati definiti in c ++ 03.
BЈовић,

1
@deworde: il commento è stato rimosso dalla risposta.
Kevin

@jozefg Se un compilatore particolare avvolge sempre numeri interi con segno, potrebbe essere considerato un'estensione del linguaggio non documentata. (Naturalmente, essere privi di documenti significa che non hai alcuna garanzia che non rimuovano l'estensione)
user253751

-6

Non seguire le regole SE il tuo progetto riguarda progetti speciali, ad esempio un progetto governativo o un esercito, ma devi seguire le regole SE stai parlando di un progetto open source o di grandi dimensioni con un team distribuito.


2
senza una spiegazione, questa risposta potrebbe diventare inutile nel caso in cui qualcun altro pubblichi un'opinione opposta. Ad esempio, se qualcuno pubblica un reclamo come "segui le regole SE il tuo progetto riguarda progetti speciali, ad esempio un progetto governativo o uno dell'esercito, ma non è necessario seguire le regole SE stai parlando di un open source ..." , in che modo questa risposta aiuterebbe il lettore a scegliere due opinioni opposte? Valuta di modificarlo in una forma migliore
moscerino il

2
Unown: saresti sorpreso di sapere quanti standard ci sono nei progetti GOV ...
Deer Hunter,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.