Respuestas:
Si se compara C89
con C++
, aquí hay un par de cosas.
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 agrega muchos otros casos
// 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;
es una TU legal en C, pero no en C ++.
auto a;
es válido en la revisión estándar más reciente de C ++.
a
?
auto x;
no es válido en la revisión más reciente, pero por ejemplo lo auto x = 0;
es. Al principio estaba un poco sorprendido :)
C ++ también tiene nuevas palabras clave. El siguiente es un código C válido, pero no se compilará en C ++:
int class = 1;
int private = 2;
int public = 3;
int virtual = 4;
Hay muchas cosas. Solo un ejemplo simple (debería ser suficiente para demostrar que C no es un subconjunto adecuado de C ++):
int* test = malloc(100 * sizeof(int));
debería compilarse en C pero no en C ++.
int*
.
void *
, que en C se puede asignar a cualquier tipo de puntero, y C ++ no se puede asignar a ningún otro tipo de puntero.
En C ++, si declara una struct
, union
o enum
, su nombre es inmediatamente accesible sin ningún tipo de calificativos:
struct foo { ... };
foo x; // declare variable
En C, esto no funcionará, porque los tipos así declarados viven en sus propios espacios de nombres distintos. Por tanto, tienes que escribir:
struct foo { ... };
struct foo x; // declare variable
Note la presencia de struct
allí en la segunda línea. Tienes que hacer lo mismo para union
y enum
(usando sus respectivas palabras clave), o usar el typedef
truco:
typedef struct { ... } foo;
foo x; // declare variable
En consecuencia, puede tener varios tipos de diferentes tipos con el mismo nombre en C, ya que puede eliminar la ambigüedad:
struct foo { ... };
typedef enum { ... } foo;
struct foo x;
foo y;
En C ++, sin embargo, aunque puede prefijar un struct
nombre con una palabra clave struct
siempre que haga referencia a él, los espacios de nombres se combinan, por lo que el fragmento de C anterior no es válido. Por otro lado, C ++ específicamente hace una excepción para permitir que un tipo y un typedef para ese tipo tengan el mismo nombre (obviamente sin efecto), para permitir el uso de typedef
trucos sin cambios de C.
struct
, union
y enum
) comparten el mismo espacio de nombres. Un mejor ejemplo seríastruct foo { ... }; typedef enum { ... } foo;
Esto también depende de la variedad de C que esté utilizando. Stroustrup hizo C ++ tan compatible como pudo, y no más compatible, con las normas ANSI de 1989 e ISO de 1990, y la versión de 1995 no cambió nada. El comité de C tomó una dirección algo diferente con el estándar de 1999, y el comité de C ++ ha cambiado el siguiente estándar de C ++ (probablemente el próximo año más o menos) para ajustarse a algunos de los cambios.
Stroustrup enumera las incompatibilidades con C90 / C95 en el Apéndice B.2 de "El lenguaje de programación C ++", Edición especial (que es la tercera edición con algo de material agregado):
'a'
es un int
en C, un char
en C ++.
El tamaño de una enumeración está int
en C, no necesariamente en C ++.
C ++ tiene //
comentarios hasta el final de la línea, C no (aunque es una extensión común).
En C ++, una struct foo {
definición se coloca foo
en el espacio de nombres global, mientras que en C tendría que denominarse struct foo
. Esto permite que una struct
definición oculte un nombre en un ámbito externo y tiene algunas otras consecuencias. Además, C permite un mayor alcance para las struct
definiciones y las permite en declaraciones de tipo de retorno y tipo de argumento.
C ++ es más exigente con los tipos en general. No permitirá que se asigne un número entero a un enum
, y los void *
objetos no se pueden asignar a otros tipos de puntero sin una conversión. En C, es posible proporcionar un inicializador demasiado grande (char name[5] = "David"
donde C descartará el carácter nulo final).
C89 se permite implícitamente int
en muchos contextos y C ++ no. Esto significa que todas las funciones deben declararse en C ++, mientras que en C89 a menudo era posible asumir int
todo lo aplicable en la declaración de función.
En C, es posible saltar del exterior de un bloque al interior utilizando una declaración etiquetada. En C ++, esto no está permitido si se salta una inicialización.
C es más liberal en el enlace externo. En C, una const
variable global es implícita extern
, y eso no es cierto en C ++. C permite que un objeto de datos global se declare varias veces sin unextern
, pero eso no es cierto en C ++.
Muchas palabras clave de C ++ no son palabras clave en C o están #define
d en encabezados C estándar.
También hay algunas características antiguas de C que ya no se consideran de buen estilo. En C, puede declarar una función con las definiciones de los argumentos después de la lista de argumentos. En C, una declaración como int foo()
significa que foo()
puede tomar cualquier número de cualquier tipo de argumentos, mientras que en C ++ es equivalente a int foo(void)
.
Eso parece cubrir todo, desde Stroustrup.
Si usa gcc, puede usar la advertencia -Wc++-compat
para darle advertencias sobre el código C que es dudoso en C ++ de alguna manera. Actualmente se utiliza en gcc y ha mejorado mucho recientemente (tal vez pruebe una versión nocturna para obtener lo mejor que pueda).
(Esto no responde estrictamente a la pregunta, pero a la gente le puede gustar).
Creo que la mayor diferencia es que este es un archivo fuente C válido:
int main()
{
foo();
}
Tenga en cuenta que no he declarado en foo
ningún lado.
Aparte de las diferencias de idioma, C ++ también realiza algunos cambios en la biblioteca que heredó de C, por ejemplo, algunas funciones devuelven en const char *
lugar de char *
.
s,C,C89,
y tenga en cuenta que es un archivo fuente C99 no válido.
#include <stdio.h>
int new (int n) {
return n/2;
}
int main(void) {
printf("%d\n", new(10));
return 0;
}
Consulte también la entrada de preguntas frecuentes de C ++ .
Algunas de las respuestas aquí cubren diferencias de sintaxis que harían que los compiladores de C ++ fallaran en el código fuente C89 (o C99). Sin embargo, existen algunas diferencias sutiles de idioma que son legales en ambos idiomas pero que producirían un comportamiento diferente. La sizeof (char)
diferencia que mencionó Naveen es un ejemplo, pero escriba un programa que imprima "C" si se compila como un programa (ANSI) C, y "C ++" si se compila como un programa C ++ enumera algunos otros.
Los compiladores de C generalmente permitieron un pequeño corte de esquina que C ++ no permite. C ++ es mucho más estricto que C. Y, en general, algunas de estas diferencias dependen del compilador. g ++ permite algunas cosas que el compilador Intel C ++ no permite, por ejemplo. Incluso el código C bastante bien escrito no se compilará con un compilador C ++ moderno.
No puede comparar idiomas solo por sintaxis. Si lo hace, tal vez pueda ver a C como un subconjunto de C ++. En mi opinión, el hecho de que C ++ sea OO (y C no) es suficiente para decir que C y C ++ son lenguajes diferentes.