Domanda

IL Articolo di Wikipedia sull'ANSI C dice:

Uno degli obiettivi del processo di standardizzazione ANSI C era quello di produrre un superset di K&R C (il primo standard pubblicato), incorporando molte delle funzionalità non ufficiali successivamente introdotte.Tuttavia, il comitato per gli standard ha incluso anche diverse nuove funzionalità, come prototipi di funzioni (presi in prestito dal linguaggio di programmazione C++) e un preprocessore più capace.Anche la sintassi per le dichiarazioni dei parametri è stata modificata per riflettere lo stile C++.

Questo mi fa pensare che ci siano delle differenze.Tuttavia, non ho visto un confronto tra K&R C e ANSI C.Esiste un documento del genere?In caso contrario, quali sono le differenze principali?

MODIFICARE:Credo che il libro K&R dica "ANSI C" sulla copertina.Almeno credo che lo faccia la versione che ho a casa.Quindi forse non c'è più alcuna differenza?

È stato utile?

Soluzione

Potrebbe esserci un po' di confusione su cosa sia "K&R C".Il termine si riferisce al linguaggio come documentato nella prima edizione di "The C Programming Language". In parole povere:il linguaggio di input del compilatore C dei Bell Labs intorno al 1978.

Kernighan e Ritchie furono coinvolti nel processo di standardizzazione ANSI.Il dialetto "ANSI C" ha sostituito "K&R C" e le successive edizioni di "The C Programming Language" adottano le convenzioni ANSI."K&R C" è un "linguaggio morto", tranne nella misura in cui alcuni compilatori accettano ancora codice legacy.

Altri suggerimenti

I prototipi funzionali rappresentavano il cambiamento più evidente tra K&R C e C89, ma ce n'erano molti altri.È stato dedicato molto lavoro importante anche alla standardizzazione della libreria C.Anche se la libreria C standard era una codificazione della pratica esistente, la codificava multiplo pratiche esistenti, che lo hanno reso più difficile.P.J.Il libro di Plauger, La libreria C standard, è un ottimo riferimento e racconta anche alcuni dettagli dietro le quinte Perché la biblioteca è finita così.

Lo standard ANSI/ISO C è molto simile a K&R C sotto molti aspetti.Era previsto che la maggior parte del codice C esistente dovesse basarsi su compilatori ANSI senza molte modifiche.Tuttavia, nell’era pre-standard, la semantica del linguaggio era aperta all’interpretazione da parte di ciascun fornitore di compilatori.ANSI C ha introdotto una descrizione comune della semantica del linguaggio che ha messo tutti i compilatori su un piano di parità.È facile darlo per scontato ora, circa 20 anni dopo, ma si è trattato di un risultato significativo.

Nella maggior parte dei casi, se non hai una base di codice C pre-standard da mantenere, dovresti essere felice di non doverti preoccupare.Se lo fai, o peggio ancora, se stai cercando di portare un vecchio programma a standard più moderni, allora hai la mia simpatia.

Ci sono alcune piccole differenze, ma penso che le edizioni successive di K&R siano per ANSI C, quindi non c'è più alcuna differenza reale.
"C Classic" in mancanza di termini migliori aveva un modo leggermente diverso di definire le funzioni, ad es.

int f( p, q, r )  
int p, float q, double r;  
{  
    // Code goes here  
}

Credo che l'altra differenza fossero i prototipi funzionali.I prototipi non dovevano (in effetti non potevano) prendere un elenco di argomenti o tipi.In ANSI C lo fanno.

  1. prototipo di funzione.
  2. qualificatori costanti e volatili.
  3. ampio supporto ai personaggi e internazionalizzazione.
  4. consentire l'utilizzo del puntatore a funzione senza dereferenziazione.

Un'altra differenza è che non era necessario definire i tipi restituiti dalle funzioni e i tipi di parametri.Si presume che siano int.

f(x)
{
    return x + 1;
}

E

int f(x)
int x;
{
    return x + 1;
}

sono identici.

  • PROTOTIPAZIONE DI FUNZIONI: ANSI C adotta la tecnica del prototipo di funzione C++ in cui la definizione e la dichiarazione della funzione includono nomi di funzioni, argomenti t, tipi di dati e tipi di dati con valore restituito. Il prototipo di funzione consente ai compilatori ANSI di verificare la chiamata di funzione nel programma utente che passa un numero non valido di argomento o tipi di dati di argomenti incompatibili. Questi risolvono un grave punto debole dei compilatori K&R C: chiamate non valide nel programma utente spesso superano la compilazione ma causano l'arresto anomalo del programma quando vengono eseguite

La differenza è:

  1. Prototipo
  2. ampio supporto ai personaggi e internazionalizzazione
  3. Supporto per parole chiave const e volatili
  4. consentire l'utilizzo dei puntatori a funzioni come dereferenziazione

Le principali differenze tra ANSI C e K&R C sono le seguenti:

  • prototipazione di funzioni
  • supporto dei qualificatori del tipo di dati const e volatile
  • supportare caratteri ampi e l'internazionalizzazione
  • consentire l'utilizzo dei puntatori a funzione senza dereferenziazione

ANSI C adotta la tecnica del prototipo di funzione C++ in cui la definizione e la dichiarazione della funzione includono nomi di funzioni, tipi di dati di argomenti e tipi di dati di valore restituito.Il prototipo di funzione consente al compilatore ANSI C di verificare la presenza di chiamate di funzione nei programmi utente che passano numeri di argomenti non validi o tipi di dati di argomenti incompatibili.Questi risolvono i principali punti deboli del compilatore K&R C.

Esempio:to dichiara una funzione foo e richiede che foo prenda due argomenti

 unsigned long foo (char* fmt, double data)
 {
      /*body of foo */
 }

La differenza più grande, credo, è la prototipazione delle funzioni e la sintassi per descrivere i tipi di argomenti delle funzioni.

Una differenza importante che nessuno ha ancora menzionato è che prima dell'ANSI, il C era definito in gran parte da precedenti piuttosto che da specifiche;nei casi in cui determinate operazioni avrebbero conseguenze prevedibili su alcune piattaforme ma non su altre (ad es.utilizzando operatori relazionali su due puntatori non correlati), il precedente era fortemente favorevole a rendere disponibili al programmatore le garanzie della piattaforma.Per esempio:

  1. Sulle piattaforme che definiscono una classificazione naturale tra tutti i puntatori a tutti gli oggetti, si potrebbe fare affidamento sull'applicazione degli operatori relazionali a puntatori arbitrari per ottenere tale classificazione.

  2. Sulle piattaforme in cui il mezzo naturale per verificare se un puntatore è "maggiore di" un altro non ha mai alcun effetto collaterale oltre a produrre un valore vero o falso, si potrebbe allo stesso modo fare affidamento sull'applicazione degli operatori relazionali a puntatori arbitrari per non avere mai alcun lato -effetti diversi dalla produzione di un valore vero o falso.

  3. Sulle piattaforme in cui due o più tipi interi condividevano la stessa dimensione e rappresentazione, si poteva fare affidamento su un puntatore a qualsiasi tipo intero di questo tipo per leggere o scrivere informazioni di qualsiasi altro tipo con la stessa rappresentazione.

  4. Sulle piattaforme in complemento a due in cui gli overflow di numeri interi si svolgono naturalmente in modo silenzioso, si può fare affidamento su un'operazione che coinvolge valori senza segno inferiori a "int" per comportarsi come se il valore fosse senza segno nei casi in cui il risultato sarebbe compreso tra INT_MAX+1u e UINT_MAX e non è stato promosso a un tipo più grande, né utilizzato come operando sinistro di >>, né alcuno degli operandi di /, %, o qualsiasi operatore di confronto. Per inciso, la logica dello standard indica questo come uno dei motivi per cui i tipi piccoli senza segno vengono promossi a firmati.

Prima del C89, non era chiaro fino a che punto ci si potesse aspettare che i compilatori per piattaforme in cui i presupposti di cui sopra non sarebbero naturalmente validi riuscissero a sostenere tali presupposti, ma c'erano pochi dubbi sul fatto che i compilatori per piattaforme che potevano facilmente ed economicamente sostenere tali presupposti dovrebbe farlo.Gli autori dello standard C89 non si sono presi la briga di dirlo espressamente perché:

  1. I compilatori i cui scrittori non erano deliberatamente ottusi avrebbero continuato a fare tali cose quando possibile senza che glielo dicessero (la logica fornita per promuovere piccoli valori senza segno in firmato rafforza fortemente questo punto di vista).

  2. Lo standard richiedeva solo che le implementazioni fossero in grado di eseguire un programma possibilmente inventato senza un overflow dello stack e riconosceva che mentre un'implementazione ottusa poteva trattare qualsiasi altro programma come se invocasse un comportamento indefinito, ma non pensava che valesse la pena preoccuparsi che scrittori di compilatori ottusi scrivessero implementazioni “conformi” ma inutili.

Sebbene "C89" sia stato interpretato contemporaneamente come "il linguaggio definito da C89, più qualsiasi funzionalità e garanzia aggiuntiva fornita dalla piattaforma", gli autori di gcc hanno spinto un'interpretazione che esclude qualsiasi funzionalità e garanzia oltre quelle richieste da C89.

Nonostante tutte le affermazioni al contrario, K&R era ed è perfettamente in grado di fornire qualsiasi tipo di materiale, dal basso all'hardware in su.Il problema ora è trovare un compilatore (preferibilmente gratuito) che possa fornire una compilazione pulita su un paio di milioni di righe di K&R C senza doverlo modificare e che funzioni su qualcosa come un processore multi core AMD.

Per quanto posso vedere, dopo aver esaminato il sorgente della serie GCC 4.x.x non esiste un semplice hack per riattivare le funzionalità di ritardo -traditional e -cpp-traditional al loro stato di funzionamento precedente senza uno sforzo maggiore di quello che sono disposto a fare mettere in.È più semplice creare da zero un compilatore pre-ansi K&R.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top