[c++] ¿Puede el código que es válido tanto en C como en C ++ producir un comportamiento diferente cuando se compila en cada idioma?


7 Answers

Aquí hay un ejemplo que aprovecha la diferencia entre llamadas a funciones y declaraciones de objetos en C y C ++, así como el hecho de que C90 permite la invocación de funciones no declaradas:

#include <stdio.h>

struct f { int x; };

int main() {
    f();
}

int f() {
    return printf("hello");
}

En C ++ esto no imprimirá nada porque se crea y se destruye un f temporal, pero en C90 se imprimirá hello porque las funciones se pueden invocar sin haber sido declaradas.

En caso de que te estés preguntando si el nombre f se usa dos veces, los estándares C y C ++ lo permiten explícitamente, y para hacer un objeto tienes que decir struct f para desambiguar si quieres la estructura, o dejar de struct si quieres la función .

Question

C y C ++ tienen muchas diferencias, y no todos los códigos C válidos son códigos C ++ válidos.
(Por "válido" me refiero a un código estándar con un comportamiento definido, es decir, no específico de la implementación / indefinido / etc.)

¿Hay algún escenario en el que un fragmento de código válido tanto en C como en C ++ produzca un comportamiento diferente cuando se compila con un compilador estándar en cada idioma?

Para que sea una comparación razonable / útil (estoy tratando de aprender algo útil en la práctica, no tratar de encontrar lagunas obvias en la pregunta), supongamos:

  • Nada relacionado con el preprocesador (lo que significa que no hay hacks con #ifdef __cplusplus , pragmas, etc.)
  • Todo lo definido en la implementación es el mismo en ambos idiomas (por ejemplo, límites numéricos, etc.)
  • Estamos comparando versiones razonablemente recientes de cada estándar (por ejemplo, C ++ 98 y C90 o posterior)
    Si las versiones importan, entonces mencione qué versiones de cada producto producen un comportamiento diferente.



Por C ++ 11 estándar:

a. El operador de coma realiza la conversión lvalue-a-rvalue en C pero no en C ++:

   char arr[100];
   int s = sizeof(0, arr);       // The comma operator is used.

En C ++, el valor de esta expresión será 100 y en C esto será sizeof(char*) .

segundo. En C ++, el tipo de enumerador es su enumeración. En C, el tipo de enumerador es int.

   enum E { a, b, c };
   sizeof(a) == sizeof(int);     // In C
   sizeof(a) == sizeof(E);       // In C++

Esto significa que sizeof(int) puede no ser igual a sizeof(E) .

do. En C ++ una función declarada con lista de parámetros vacía no toma argumentos. En C, la lista de parámetros vacíos significa que el número y tipo de parámetros de función se desconoce.

   int f();           // int f(void) in C++
                      // int f(*unknown*) in C



Otro listado por el Estándar C ++:

#include <stdio.h>

int x[1];
int main(void) {
    struct x { int a[2]; };
    /* size of the array in C */
    /* size of the struct in C++ */
    printf("%d\n", (int)sizeof(x)); 
}



C90 vs. C ++ 11 ( int frente a double ):

#include <stdio.h>

int main()
{
  auto j = 1.5;
  printf("%d", (int)sizeof(j));
  return 0;
}

En C auto significa variable local. En C90 está bien omitir la variable o el tipo de función. Por defecto es int . En C ++ 11 auto significa algo completamente diferente, le dice al compilador que infiera el tipo de la variable del valor utilizado para inicializarla.




struct abort
{
    int x;
};

int main()
{
    abort();
    return 0;
}

Devuelve con el código de salida de 0 en C ++ o 3 en C.

Este truco probablemente podría usarse para hacer algo más interesante, pero no podía pensar en una buena forma de crear un constructor que fuera aceptable para C. Intenté hacer un ejemplo similarmente aburrido con el constructor de copias, eso dejaría un argumento ser aprobado, aunque de una manera no portátil:

struct exit
{
    int x;
};

int main()
{
    struct exit code;
    code.x=1;

    exit(code);

    return 0;
}

Sin embargo, VC ++ 2005 se negó a compilar eso en el modo C ++, quejándose de cómo se redefinió el "código de salida". (Creo que esto es un error del compilador, a menos que de repente haya olvidado cómo programarlo). Salió con un código de salida de proceso de 1 cuando se compiló como C.




Una castaña antigua que depende del compilador de C, sin reconocer los comentarios de final de línea de C ++ ...

...
int a = 4 //* */ 2
        +2;
printf("%i\n",a);
...



No olvides la distinción entre los espacios de nombres globales C y C ++. Supongamos que tiene un foo.cpp

#include <cstdio>

void foo(int r)
{
  printf("I am C++\n");
}

y un foo2.c

#include <stdio.h>

void foo(int r)
{
  printf("I am C\n");
}

Ahora supongamos que tiene main.c y main.cpp que se ven así:

extern void foo(int);

int main(void)
{
  foo(1);
  return 0;
}

Cuando se compila como C ++, usará el símbolo en el espacio de nombres global de C ++; en C utilizará el C:

$ diff main.cpp main.c
$ gcc -o test main.cpp foo.cpp foo2.c
$ ./test 
I am C++
$ gcc -o test main.c foo.cpp foo2.c
$ ./test 
I am C



#include <stdio.h>

int main(void)
{
    printf("%d\n", (int)sizeof('a'));
    return 0;
}

En C, esto imprime cualquiera que sea el valor de sizeof(int) en el sistema actual, que normalmente es 4 en la mayoría de los sistemas comúnmente en uso en la actualidad.

En C ++, esto debe imprimir 1.




Related



Tags

c++ c++   c