Risposte:
Se ti confronti C89con, C++ecco un paio di cose
int n;
int n; // ill-formed: n already defined
int a[1];
int (*ap)[] = &a; // ill-formed: a does not have type int[]
int b(a) int a; { } // ill-formed: grammar error
struct A { struct B { int a; } b; int c; };
struct B b; // ill-formed: b has incomplete type (*not* A::B)
auto a; // ill-formed: type-specifier missing
C99 aggiunge un sacco di altri casi
// ill-formed: invalid syntax
void f(int p[static 100]) { }
// ill-formed: n is not a constant expression
int n = 1;
int an[n];
// ill-formed: fam has incomplete type
struct A { int a; int fam[]; };
// ill-formed: two names for one parameter?
void copy(int *restrict src, int *restrict dst);
typedef;è una TU legale in C, ma non in C ++.
auto a;è valido nella più recente revisione dello standard C ++.
a?
auto x;non è valido nella revisione più recente, ma ad esempio lo auto x = 0;è.
Anche il C ++ ha nuove parole chiave. Quanto segue è un codice C valido ma non verrà compilato in C ++:
int class = 1;
int private = 2;
int public = 3;
int virtual = 4;
Ci sono molte cose. Solo un semplice esempio (dovrebbe essere sufficiente per dimostrare che C non è un sottoinsieme appropriato di C ++):
int* test = malloc(100 * sizeof(int));
dovrebbe essere compilato in C ma non in C ++.
int*.
void *, che in C può essere assegnato a qualsiasi tipo di puntatore e C ++ non può essere assegnato a nessun altro tipo di puntatore.
In C ++, se si dichiara una struct, uniono enum, il suo nome è immediatamente accessibile senza qualificazioni:
struct foo { ... };
foo x; // declare variable
In C, questo non funzionerà, perché i tipi così dichiarati vivono nei loro spazi dei nomi distinti. Quindi, devi scrivere:
struct foo { ... };
struct foo x; // declare variable
Notare la presenza di structlì sulla seconda riga. Devi fare lo stesso per unione enum(usando le rispettive parole chiave) o usare il typedeftrucco:
typedef struct { ... } foo;
foo x; // declare variable
Di conseguenza, puoi avere diversi tipi di tipi diversi con lo stesso nome in C, poiché puoi disambiguare:
struct foo { ... };
typedef enum { ... } foo;
struct foo x;
foo y;
In C ++, tuttavia, sebbene sia possibile anteporre a un structnome una parola chiave structogni volta che ci si fa riferimento, gli spazi dei nomi vengono uniti e quindi lo snippet C precedente non è valido. D'altra parte, C ++ fa specificamente un'eccezione per consentire a un tipo e un typedef per quel tipo di avere lo stesso nome (ovviamente senza alcun effetto), per consentire l'uso del typedeftrucco invariato da C.
struct, unione enum) condividono lo stesso spazio dei nomi. Un esempio migliore potrebbe esserestruct foo { ... }; typedef enum { ... } foo;
Questo dipende anche dalla varietà di C che stai usando. Stroustrup ha reso C ++ il più compatibile possibile, e non più compatibile, con gli standard ANSI del 1989 e ISO del 1990, e la versione del 1995 non ha cambiato nulla. Il comitato C è andato in una direzione un po 'diversa con lo standard del 1999, e il comitato C ++ ha cambiato il prossimo standard C ++ (probabilmente uscito il prossimo anno o giù di lì) per conformarsi ad alcune delle modifiche.
Stroustrup elenca le incompatibilità con C90 / C95 nell'Appendice B.2 di "The C ++ Programming Language", edizione speciale (che è la terza edizione con del materiale aggiunto):
'a'è una intin C, una charin C ++.
La dimensione di un'enumerazione è intin C, non necessariamente in C ++.
C ++ ha //commenti alla fine della riga, C no (sebbene sia un'estensione comune).
In C ++, una struct foo {definizione viene fooinserita nello spazio dei nomi globale, mentre in C dovrebbe essere indicata come struct foo. Ciò consente a una structdefinizione di nascondere un nome in un ambito esterno e ha alcune altre conseguenze. Inoltre, C consente un ambito più ampio per le structdefinizioni e le consente nelle dichiarazioni di tipo restituito e tipo di argomento.
Il C ++ è più pignolo sui tipi in generale. Non consentirà l'assegnazione di un intero a un oggetto enume gli void *oggetti non possono essere assegnati ad altri tipi di puntatore senza un cast. In C, è possibile fornire un inizializzatore troppo grande (char name[5] = "David" dove C eliminerà il carattere null finale).
C89 consentiva implicito intin molti contesti e C ++ no. Ciò significa che tutte le funzioni devono essere dichiarate in C ++, mentre in C89 era spesso possibile cavarsela assumendo intper tutto ciò che era applicabile nella dichiarazione di funzione.
In C, è possibile saltare dall'esterno di un blocco all'interno utilizzando un'istruzione etichettata. In C ++, questo non è consentito se salta un'inizializzazione.
C è più liberale nei collegamenti esterni. In C, una constvariabile globale è implicitamente externe non è vero in C ++. C consente a un oggetto dati globale di essere dichiarato più volte senza un extern, ma non è vero in C ++.
Molte parole chiave C ++ non sono parole chiave in C o sono #defined nelle intestazioni C standard.
Ci sono anche alcune vecchie funzionalità di C che non sono più considerate un buon stile. In C, puoi dichiarare una funzione con le definizioni degli argomenti dopo l'elenco degli argomenti. In C, una dichiarazione come int foo()significa che foo()può accettare qualsiasi numero di qualsiasi tipo di argomenti, mentre in C ++ è equivalente a int foo(void).
Questo sembra coprire tutto da Stroustrup.
Se usi gcc, puoi usare l'avviso -Wc++-compat per darti avvisi sul codice C che è in qualche modo dubbio in C ++. È attualmente utilizzato nello stesso gcc e recentemente è migliorato molto (magari prova una versione notturna per ottenere il meglio che puoi).
(Questo non risponde rigorosamente alla domanda, ma alla gente potrebbe piacere).
L'unica più grande differenza che penso è che questo è un file sorgente C valido:
int main()
{
foo();
}
Nota che non ho dichiarato foo nessuna parte.
A parte le differenze di linguaggio, C ++ apporta anche alcune modifiche alla libreria che ha ereditato da C, ad esempio alcune funzioni restituiscono const char *invece di char *.
s,C,C89,e notare che si tratta di un file sorgente C99 non valido.
#include <stdio.h>
int new (int n) {
return n/2;
}
int main(void) {
printf("%d\n", new(10));
return 0;
}
Vedere anche la voce delle domande frequenti su C ++ .
Un certo numero di risposte qui copre differenze di sintassi che causerebbero il fallimento dei compilatori C ++ sul codice sorgente C89 (o C99). Tuttavia, ci sono alcune sottili differenze linguistiche che sono legali in entrambe le lingue ma che produrrebbero comportamenti diversi. La sizeof (char)differenza menzionata da Naveen è un esempio, ma Scrivi un programma che stamperà "C" se compilato come un programma C (ANSI) e "C ++" se compilato come un programma C ++ ne elenca alcuni altri.
I compilatori C generalmente consentivano un piccolo taglio degli angoli che C ++ non fa. Il C ++ è molto più rigoroso di C. E generalmente, alcune di queste differenze dipendono dal compilatore. g ++ consente alcune cose che il compilatore Intel C ++ non, ad esempio. Anche il codice C scritto abbastanza bene non verrà compilato con un moderno compilatore C ++.
Non è possibile confrontare le lingue solo in base alla sintassi. Se lo fai, forse puoi vedere C come un sottoinsieme di C ++. Secondo me il fatto che C ++ sia OO (e C non lo è) è sufficiente per dire che C e C ++ sono linguaggi diversi.