Leí en muchos libros que C es un subconjunto de C ++.
Algunos libros dicen que C es un subconjunto de C ++, excepto por los pequeños detalles .
¿Cuáles son algunos casos en los que el código se compilará en C, pero no en C ++?
Si se compara C89con 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 loauto x = 0;es. Al principio estaba un poco sorprendido :)En C,
sizeof('a')es igual asizeof(int).En C ++,
sizeof('a')es igual asizeof(char).fuente
'a'es unint. En C ++,'a'es unchar.C ++ también tiene nuevas palabras clave. El siguiente es un código C válido, pero no se compilará en C ++:
fuente
Hay muchas cosas. Solo un ejemplo simple (debería ser suficiente para demostrar que C no es un subconjunto adecuado de C ++):
debería compilarse en C pero no en C ++.
fuente
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,unionoenum, su nombre es inmediatamente accesible sin ningún tipo de calificativos:En C, esto no funcionará, porque los tipos así declarados viven en sus propios espacios de nombres distintos. Por tanto, tienes que escribir:
Note la presencia de
structallí en la segunda línea. Tienes que hacer lo mismo paraunionyenum(usando sus respectivas palabras clave), o usar eltypedeftruco:En consecuencia, puede tener varios tipos de diferentes tipos con el mismo nombre en C, ya que puede eliminar la ambigüedad:
En C ++, sin embargo, aunque puede prefijar un
structnombre con una palabra clavestructsiempre 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 detypedeftrucos sin cambios de C.fuente
struct,unionyenum) 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 uninten C, uncharen C ++.El tamaño de una enumeración está
inten 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 colocafooen el espacio de nombres global, mientras que en C tendría que denominarsestruct foo. Esto permite que unastructdefinición oculte un nombre en un ámbito externo y tiene algunas otras consecuencias. Además, C permite un mayor alcance para lasstructdefiniciones 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 losvoid *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
inten muchos contextos y C ++ no. Esto significa que todas las funciones deben declararse en C ++, mientras que en C89 a menudo era posible asumirinttodo 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
constvariable global es implícitaextern, 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
#defined 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 quefoo()puede tomar cualquier número de cualquier tipo de argumentos, mientras que en C ++ es equivalente aint foo(void).Eso parece cubrir todo, desde Stroustrup.
fuente
Si usa gcc, puede usar la advertencia
-Wc++-compatpara 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).
fuente
Creo que la mayor diferencia es que este es un archivo fuente C válido:
Tenga en cuenta que no he declarado en
fooningú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 dechar *.fuente
s,C,C89,y tenga en cuenta que es un archivo fuente C99 no válido.Consulte también la entrada de preguntas frecuentes de C ++ .
fuente
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.fuente
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.
fuente
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.
fuente