versiones informacion historia descargar caracteristicas c++ c c++11 c99

informacion - ¿Cuáles son las diferencias incompatibles entre C(99) y C++(11)?



historia de c++ (4)

Esta pregunta fue desencadenada por replie (s) a una publicación de Herb Sutter donde explicaba la decisión de MS de no admitir / hacer un compilador C99, pero de todas formas se ajustaba a las características C (99) que están en el estándar C ++ (11).

Un comentarista respondió :

(...) C es importante y merece al menos un poco de atención.

Hay MUCHO código existente que es válido C pero no es válido C ++. Es probable que ese código no se reescriba (...)

Como solo programo en MS C ++, realmente no conozco el C "puro", es decir, no tengo una imagen clara de qué detalles del C ++ - el lenguaje que estoy usando no está en C (99) y tengo poco pistas donde algún código C99 no funcionaría como está en un compilador de C ++.

Tenga en cuenta que sé que C99 solo restrict palabra clave, que a mí me parece que tiene una aplicación muy limitada y sobre arreglos de longitud variable (de los cuales no estoy seguro de qué tan extendidos o importantes son).

Además, estoy muy interesado en si hay diferencias semánticas o errores importantes, es decir, código C (99) que compilará bajo C ++ (11) pero que hará algo diferente con el compilador C ++ que con el compilador C.

Enlaces rápidos: recursos externos de las respuestas:


En C ++, configurar un miembro de una unión y acceder al valor de un miembro diferente es un comportamiento indefinido, mientras que no está indefinido en C99.

Hay muchas otras diferencias enumeradas en la page wikipedia.


Hay un montón de incompatibilidades que han existido por edades (C90 o anterior), así como un montón de características realmente agradables en C99 y C11. Estos son todos fuera de mi cabeza.

// Valid C int *array = malloc(sizeof(*array) * n); // Valid C and valid C++, extra typing, it''s always extra typing... int *array = (int *) malloc(sizeof(*array) * n); // Valid C++ int *array = new int[n];

C99 es agradable y los programadores de C en todas partes deberían usarlo

Las nuevas funciones en C99 son muy buenas para la programación general. Los VLA y los restrict no están (en mi opinión) dirigidos para uso general, sino principalmente para llevar a FORTRAN y programadores numéricos a C (aunque restrict ayuda al autovectorizador). Dado que cualquier programa conforme que use restrict funcionará exactamente de la misma manera (pero posiblemente no tan rápido) si #define restrict en la parte superior del archivo, no es un gran problema. Los VLA son bastante raros en la naturaleza, parece.

Los miembros flexibles de la matriz pueden ser agradables. Tenga en cuenta que estos NO son lo mismo que las matrices de longitud variable. La gente ha estado usando este truco durante años, pero el soporte oficial significa menos tipeo y también nos permite hacer constantes en tiempo de compilación. (La forma antigua era tener una matriz de tamaño 1, pero luego calcular el tamaño de la asignación es una verdadera molestia).

struct lenstr { unsigned length; char data[]; }; // compile time constant const struct lenstr hello = { 12, "hello, world" };

Inicializadores designados. Ahorra mucho tipeo

struct my_struct { int a; char *b; int c; const char *d; }; struct my_struct x = { .a = 15, .d = "hello" // implicitly sets b = NULL and c = 0 }; int hex_digits[256] = { [''0''] = 0, [''1''] = 1, [''2''] = 2, /* etc */ [''f''] = 15 };

La palabra clave en inline comporta de manera diferente, puede elegir qué unidad de traducción obtiene una versión no en línea de una función declarada en línea agregando una declaración externa a esa unidad.

Literales compuestos.

struct point { float x; float y; }; struct point xy_from_polar(float r, float angle) { return (struct point) { cosf(angle) * r, sinf(angle) * r }; }

La función snprintf está probablemente en mi top 10 de las funciones de biblioteca más útiles en C. No solo falta en C ++, sino que el tiempo de ejecución de MSVC solo proporciona una función llamada _snprintf , que no garantiza la adición de un terminador NUL a la cadena. ( snprintf está en C ++ 11, pero todavía brilla por su ausencia en el tiempo de ejecución MSVC C).

Estructuras y uniones anónimas (C11, pero la extensión de GCC desde siempre) (las uniones anónimas están aparentemente en C ++ 03, sin compatibilidad de MSVC en modo C):

struct my_value { int type; union { int as_int; double as_double; }; // no field name! };

Como puede ver, muchas de estas características solo le ahorran mucho tipeo (literales compuestos), o hacen que los programas sean más fáciles de depurar (miembros de matriz flexibles), hacen que sea más fácil evitar errores (inicializadores designados / olvido para inicializar campos de estructura). Estos no son cambios drásticos.

En cuanto a las diferencias semánticas, estoy seguro de que las reglas de aliasing son diferentes, pero la mayoría de los compiladores lo perdonan lo suficiente en estos días que no estoy seguro de cómo construirías un caso de prueba para demostrar. La diferencia entre C y C ++ a la que todos llegan es la antigua expresión sizeof(''a'') , que siempre es 1 para C ++ pero generalmente 4 en un sistema C de 32 bits. Pero a nadie le importa qué sizeof(''a'') sea ​​de todos modos. Sin embargo, hay algunas garantías en el estándar C99 que codifican las prácticas existentes.

Toma el siguiente código. Utiliza un truco común para definir tipos de unión en C sin desperdiciar almacenamiento adicional. Creo que esto es semánticamente válido C99 y creo que esto es C ++ semánticamente dudoso, pero podría estar equivocado.

#define TAG_FUNKY_TOWN 5 struct object { int tag; }; struct funky_town { int tag; char *string; int i; }; void my_function(void) { struct object *p = other_function(); if (p->tag == TAG_FUNKY_TOWN) { struct funky_town *ft = (struct funky_town *) p; puts(ft->string); } }

Es una pena, sin embargo. El generador de código MSVC es agradable, lástima que no haya un front-end C99.



Si comienza desde el subconjunto común de C y C ++, a veces llamado limpio C (que no es del todo C90), debe considerar 3 tipos de incompatibilidades:

  1. Las características adicionales de C ++ que hacen legal C ilegal C ++

    Ejemplos de esto son palabras clave de C ++ que pueden usarse como identificadores en C o conversiones que están implícitas en C pero requieren un molde explícito en C ++.

    Esta es probablemente la razón principal por la cual Microsoft aún envía una interfaz C: de lo contrario, el código heredado que no compila como C ++ tendría que ser reescrito.

  2. Funciones adicionales de C que no son parte de C ++

    El lenguaje C no dejó de evolucionar después de que se bifurcó C ++. Algunos ejemplos son matrices de longitud variable, inicializadores designados y restrict . Estas características pueden ser bastante útiles, pero no son parte de ningún estándar de C ++, y algunas de ellas probablemente nunca lo hagan.

  3. Características que están disponibles tanto en C como en C ++, pero tienen una semántica diferente

    Un ejemplo de esto sería la vinculación de objetos const o funciones en inline .

Una lista de incompatibilidades entre C99 y C ++ 98 se puede encontrar aquí (que ya ha sido mencionado por Mat).

Mientras que C ++ 11 y C11 se acercaron en algunos frentes (las macros variadas ahora están disponibles en C ++, las matrices de longitud variable son ahora una característica opcional del lenguaje C), la lista de incompatibilidades también ha crecido (p. Ej., Selecciones genéricas en C y auto tipo-especificador en C ++).

Como un aparte, mientras que Microsoft ha tomado algo de calor por la decisión de abandonar C (que no es reciente), hasta donde yo sé, nadie en la comunidad de código abierto ha tomado medidas para hacer algo al respecto: sería Es bastante posible proporcionar muchas características de la C moderna a través de un compilador C-to-C ++, especialmente si se tiene en cuenta que algunas de ellas son triviales de implementar . Esto es posible en este momento usando Comeau C / C ++, que sí es compatible con C99.

Sin embargo, no es realmente un problema acuciante: personalmente, estoy bastante cómodo con el uso de GCC y Clang en Windows, y también hay alternativas patentadas para MSVC, por ejemplo, el compilador Pelles C o Intel.