Escreva uma poliglota C / C ++


27

O conceito deste desafio é bastante simples. Tudo que você precisa fazer é escrever um programa que será compilado como C válido e C ++ válido! Bem, existem algumas capturas. O programa deve se comportar de maneira diferente quando compilado em cada idioma. O programa deve ter saída diferente para cada idioma para ser considerado "se comportando de maneira diferente".

Regras

  • O programa deve ser válido em C e C ++
  • O programa deve ter saídas diferentes com base no idioma em que foi compilado.
  • #ifdef __cplusplusou outros truques "fáceis" do pré-processador são desencorajados! (Outras operações do pré-processador são perfeitamente boas, no entanto.)
  • Tente não parecer completamente óbvio que o programa faz algo diferente.

Este é um , para quem vencer a solução mais interessante e surpreendente. Diverta-se!

Exemplo:

Eu criei meu próprio programa para ver se isso era possível com #ifdeftruques:

#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 gera C++ rules!quando compilado em C ++ e C++ stinksquando compilado em C.

Explicação:

O que causa a diferença entre os idiomas é a tr()função. Ele tira proveito de uma das diferenças entre C e C ++, especificamente, como os literais de caracteres são tratados. Em C, eles são tratados como números inteiros; portanto, sizeof('!')retorna 4, em oposição a 1 em C ++. A ((...+1)&1)parte é apenas parte de uma operação bit a bit simples que retornará 1 se sizeof('!')retornar 4 e 0 se retornar 1. Esse número resultante é multiplicado pelas entradas na matriz te, em seguida, esse produto é finalmente adicionado ao caractere específico que está sendo transformado. Em C ++, o produto sempre será zero, portanto, a cadeia C++ rules!permanece inalterada. Em C, o produto sempre será o valor em te, portanto, a sequência será alterada para C++ stinks.


5
Tenho certeza de que este é um joguete de alguma coisa ...
Beta Decay

@BetaDecay É? Tentei procurar algo semelhante e não consegui encontrar nada.
Mewy

Você pode explicar como o seu programa funciona de maneira diferente (se não estragar o desafio)?
AL

Eu editei uma explicação para o meu post.
Mewy

Todos os de stackoverflow.com/questions/2038200/… podem ser usados ​​aqui - com um pouco de ofuscação.
Jerry Jeremias

Respostas:


18

O bolo é uma mentira?

Como houve muito debate sobre se o bolo é ou não uma mentira, escrevi este programa para responder a essa questão controversa.

#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;
}

Qual será o resultado?

C:

The cake is ..not a lie?

C ++:

The cake is a LIE!


1
Este. Eu gosto disso.
FUZxxl 28/02

9

Apenas alguns bolinhos

#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 não faz parte do C89
malat

8
@malat Sim, e exatamente esse fato é usado nesta solução. Para c ++, a função é int test (bool / * argumento booleano sem nome * /); e para C usa declaração int padrão, o que significa int test (int bool); então 'bool' é um nome de variável inteira.
Qwertiy

5

Eu poderia ter feito isso com um programa de 3 linhas, mas seria óbvio por que ele produz resultados diferentes para C e C ++. Então, em vez disso, comecei a escrever um programa maior com alguma estegonografia, que obtém resultados diferentes em C e 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;
}

Você precisa especificar uma linha de comando. Quando o executo na minha cópia do gcc, recebo esta saída:

>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

Como as coisas podem dar tão terrivelmente errado?


Embora outros tenham feito a mesma coisa, você o mascara muito bem.
precisa saber é o seguinte

5
#include <stdio.h>

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

4

Este funciona com C ++ 11 e mais recente e com qualquer C até o momento (antes de C11).

#include <stdio.h>

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

Veja aqui: C ++: http://ideone.com/9Gkg75 e C: http://ideone.com/eECSmr

Explora o fato de que no C ++ 11 a palavra-chave auto ganhou um novo significado. Portanto, enquanto a em C é do tipo int armazenado em um local AUTOmatic, é do tipo char no C ++ 11.

EDIT: Como FUZxxl disse que o int implícito foi removido em C11.


1
Não funciona com o C11, pois o C11 removeu a intregra implícita .
FUZxxl 28/02

@FUZxxl Obrigado, eu ajustei minha postagem.
precisa

1

Programa autoexplicativo

Isso exibirá "Este programa está escrito em C!" se compilado usando um compilador C; caso contrário, será impresso "Este programa está escrito em C ++!". Ele precisa de um 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;}

A maioria das outras postagens tira proveito da diferença do tamanho de um caractere em C vs C ++; este usa o fato de que, em C99, trueé definido como um número. Isso insere o ponto de exclamação e o terminador nulo com base no tamanho de true.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.