Escribir un políglota C / C ++


27

El concepto de este desafío es bastante simple. ¡Todo lo que tiene que hacer es escribir un programa que compilará como C válido y C ++ válido! Bueno, hay algunas capturas. El programa debe comportarse de manera diferente cuando se compila en cada idioma. El programa debe tener una salida diferente para cada idioma para ser considerado "comportándose de manera diferente".

Reglas

  • El programa debe ser válido tanto en C como en C ++
  • El programa debe tener diferentes resultados según el idioma en que se compiló.
  • #ifdef __cplusplus¡u otros trucos de preprocesador "fáciles" se desaconsejan! (Sin embargo, otras operaciones de preprocesador están perfectamente bien).
  • Trate de no hacer que parezca completamente obvio que el programa hace algo diferente.

Este es un , por lo que gana quien tenga la solución más interesante y sorprendente. ¡Que te diviertas!

Ejemplo:

Creé mi propio programa para ver si esto era posible sin #ifdeftrucos:

#include <stdio.h>
#include <string.h>

char *m="C++ rules!";

int t[11]={0,0,0,0,1,-1,-3,9,-8,82,0};

char tr(char c,int i)
{
    return c+((sizeof('!')+1)&1)*t[i];
}

int main()
{
    int i = 0;
    for(;i<strlen(m);i++)
    {
        printf("%c",tr(m[i],i));
    }
    printf("\n");
    return 0;
}

Este programa se genera C++ rules!cuando se compila en C ++ y C++ stinkscuando se compila en C.

Explicación:

Lo que causa la diferencia entre idiomas es la tr()función. Aprovecha una de las diferencias entre C y C ++, específicamente, cómo se tratan los literales char. En C, se tratan como enteros, por lo que sizeof('!')devuelve 4, a diferencia de 1 en C ++. La ((...+1)&1)parte es solo parte de una operación simple a nivel de bits que devolverá 1 si sizeof('!')devuelve 4 y 0 si devuelve 1. Ese número resultante se multiplica por las entradas en la matriz ty luego ese producto finalmente se agrega al carácter específico que se está transformando. En C ++, el producto siempre será cero, por lo que la cadena C++ rules!permanece sin cambios. En C, el producto siempre será el valor en t, por lo que la cadena cambia a C++ stinks.


55
Estoy seguro de que esto es un engaño de algo ...
Beta Decay

@BetaDecay ¿Es así? Intenté buscar algo similar y no pude encontrar nada.
Mewy

¿Puede explicar cómo funciona su programa de manera diferente (si no estropea el desafío)?
AL

@AL Edité en una explicación a mi publicación.
Mewy

Todos los de stackoverflow.com/questions/2038200/… podrían usarse aquí, con un poco de ofuscación.
Jerry Jeremiah

Respuestas:


18

¿Es el pastel una mentira?

Como ha habido mucho debate sobre si el pastel es o no una mentira, escribí este programa para responder a esta pregunta polémica.

#include <stdio.h>

// checks if two things are equal
#define EQUALS(a,b) (sizeof(a)==sizeof(b)) 

struct Cake{int Pie;}; // the cake is a pie!
typedef struct Cake Lie;
main(){
    struct CakeBox{
        struct Cake{ // the cake contains lies!
            Lie Lies[2];
        };
    };
    typedef struct Cake Cake;

    printf("The cake is ");
    if(EQUALS(Cake, Lie)){
        printf("a LIE!\n");
    }else{
        printf("..not a lie?\n");
    }
    return 0;
}

¿Cuál será el resultado?

DO:

The cake is ..not a lie?

C ++:

The cake is a LIE!


1
Esta. Me gusta esto.
FUZxxl

9

Solo algunos bools

#include <stdio.h>

int test(bool)
  {
  return sizeof(bool) == sizeof(int);
  }

int main(void)
  {
  puts(test(0) ? "C" : "C++");
  return 0;
  }

http://codepad.org/dPFou20W
http://codepad.org/Ko6K2JBH


bool no es parte de C89
malat

8
@malat Sí, y exactamente este hecho se utiliza en esta solución. Para c ++, la función es int test (bool / * argumento booleano sin nombre * /); y para C usa la declaración int predeterminada que significa int test (int bool); entonces 'bool' es un nombre de variable entera.
Qwertiy

5

Podría haber hecho esto con un programa de 3 líneas, pero sería obvio por qué produce resultados diferentes para C y C ++. Entonces, en lugar de eso, comencé a escribir un programa más grande con algo de estrategia que obtiene resultados diferentes en C y C ++ ...

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct product
{
    int quantity;
    char name[20];
    char desc[80];
}; 

struct _customer
{
    char name[80];
    struct product *products;
} customer;

int main(int argc, char *argv[])
{

struct shipment
{
    char tracking_number[40];
    int quantity;
    struct product { int model; int serial; } sku;
};

struct _supplier
{
    char name[80];
    struct shipment *shipments;
} supplier;

/* now read the command line and allocate all the space we need */

if(argc<5)
{
    printf("Usage: %s <supplier name> <# of shipments> <customer name> <# of products> ",argv[0]);
    exit(1);
}

strcpy(supplier.name,argv[1]);
int shipments_size = atoi(argv[2])*sizeof(struct shipment);
printf("Allocating %d bytes for %s shipments\n", shipments_size,supplier.name);
supplier.shipments=(struct shipment *)malloc(shipments_size);

strcpy(customer.name,argv[3]);
int products_size = atoi(argv[4])*sizeof(struct product);
printf("Allocating %d bytes for %s products\n", products_size,customer.name);

/* ... TODO ... finish the rest of this program later */

free(customer.products);
free(supplier.shipments);

return 0;
}

Necesita especificar una línea de comando. Cuando lo ejecuto en mi copia de gcc obtengo este resultado:

>g++ x.cpp

>a.exe "Bob Supplier" 1 "Jane Customer" 1
Allocating 52 bytes for Bob Supplier shipments
Allocating 104 bytes for Jane Customer products

>gcc x.c

>a.exe "Bob Supplier" 1 "Jane Customer" 1
Allocating 52 bytes for Bob Supplier shipments
Allocating 8 bytes for Jane Customer products

¿Cómo pueden salir las cosas tan horriblemente mal?


Aunque otros hicieron lo mismo, lo enmascaraste bastante bien.
kirbyfan64sos

5
#include <stdio.h>

int c[1]; 
int main() { 
   struct c { int cpp[2]; }; 
   printf("%d\n", (int)sizeof(c)/4);
}

4

Éste funciona con C ++ 11 y versiones posteriores y cualquier C hasta ahora (antes de C11).

#include <stdio.h>

int main()
{
    auto a = 'a';
    printf(sizeof(a) == sizeof(int) ? "C\n" : "C++\n");
    return 0;
}

Ver aquí: C ++: http://ideone.com/9Gkg75 y C: http://ideone.com/eECSmr

Explota el hecho de que en C ++ 11 la palabra clave auto tiene un nuevo significado. Entonces, mientras que en C es de tipo int almacenado en una ubicación AUTOmatic, es de tipo char en C ++ 11.

EDITAR: Como FUZxxl dijo que el int implícito se eliminó en C11.


1
No funciona con C11 ya que C11 ha eliminado la intregla implícita .
FUZxxl

@FUZxxl Gracias, ajusté mi publicación.
Felix Bytow

1

Programa de autodescripción

Esto imprimirá "¡Este programa está escrito en C!" si se compila usando un compilador de C; de lo contrario, imprimirá "¡Este programa está escrito en C ++!". Necesita un compilador C99.

#include <stdbool.h>
#include <stdio.h>
char str[] = "This program is written in C++ ";
#define S (sizeof(str)-sizeof(true)-sizeof(true)%4)
int main(){for(int i=S;i<=S+1;++i)str[i]=i==S?'!':'\0';puts(str);return 0;}

La mayoría de las otras publicaciones aprovechan la diferencia del tamaño de un carácter en C frente a C ++; éste usa el hecho de que, en C99, truese define como un número. Esto inserta el signo de exclamación y el terminador nulo en función del tamaño de true.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.