Написать C / C ++ полиглот


27

Концепция этой задачи довольно проста. Все, что вам нужно сделать, это написать программу, которая будет компилировать как действительный C, так и действительный C ++! Ну, есть некоторые уловы. Программа должна вести себя по-разному при компиляции на каждом языке. Программа должна иметь разные выходные данные для каждого языка, чтобы считаться «веду себя по-разному».

правила

  • Программа должна быть как на C, так и на C ++
  • Программа должна иметь разные выходные данные в зависимости от языка, на котором она была скомпилирована.
  • #ifdef __cplusplusили другие "легкие" уловки препроцессора не приветствуются! (Однако другие операции препроцессора вполне хороши.)
  • Постарайтесь не показывать совершенно очевидным, что программа делает что-то другое.

Это , поэтому победит тот, кто найдет самое интересное и удивительное решение. Повеселись!

Пример:

Я создал свою собственную программу, чтобы посмотреть, возможно ли это сделать с помощью #ifdefтрюков:

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

Эта программа выводится C++ rules!при компиляции в C ++ и C++ stinksпри компиляции в C.

Объяснение:

Что вызывает разницу между языками, так это tr()функция. Он использует одно из различий между C и C ++, а именно то, как обрабатываются символьные литералы. В C они рассматриваются как целые числа, поэтому sizeof('!')возвращает 4, а не 1 в C ++. Эта ((...+1)&1)часть является лишь частью простой побитовой операции, которая вернет 1, если sizeof('!')вернет 4, и 0, если вернет 1. Это результирующее число умножается на целые числа в массиве, tа затем этот продукт, наконец, добавляется к конкретному преобразуемому символу. В C ++ продукт всегда будет нулевым, поэтому строка C++ rules!остается неизменной. В C продукт всегда будет значением в t, поэтому строка меняется на C++ stinks.


5
Я уверен, что это обман чего-то ...
Beta Decay

@BetaDecay Это так? Я пытался найти что-то подобное, и я не мог ничего найти.
Mewy

Можете ли вы объяснить, как ваша программа работает по-другому (если это не испортит задачу)?
AL

@AL Я отредактировал в пояснении к моему посту.
Mewy

Все из stackoverflow.com/questions/2038200/… можно использовать здесь - с небольшим запутыванием.
Джерри Иеремия

Ответы:


18

Является ли торт ложью?

Поскольку было много споров о том, является ли пирог ложью, я написал эту программу, чтобы ответить на этот спорный вопрос.

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

Каким будет результат?

C:

The cake is ..not a lie?

C ++:

The cake is a LIE!


1
Это. Мне это нравится.
FUZxxl

9

Просто немного 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 не является частью C89
малат

8
@malat Да, и именно этот факт используется в этом решении. Для c ++ функция является int test (bool / * неназванный логический аргумент * /); а для C он использует объявление int по умолчанию, что означает int test (int bool); поэтому «bool» - это имя целочисленной переменной.
Qwertiy

5

Я мог бы сделать это с помощью трехстрочной программы, но тогда было бы очевидно, почему она дает разные результаты для C и C ++. Поэтому вместо этого я начал писать большую программу с некоторой стегонографией, которая дает разные результаты на C и 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;
}

Вам необходимо указать командную строку. Когда я запускаю его на своей копии gcc, я получаю такой вывод:

>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

Как все может пойти так плохо?


Хотя другие делали то же самое, вы маскировали это довольно хорошо.
kirbyfan64sos


4

Этот работает с C ++ 11 и новее и с любым C (до C11).

#include <stdio.h>

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

Смотрите здесь: C ++: http://ideone.com/9Gkg75 и C: http://ideone.com/eECSmr

Он использует тот факт, что в C ++ 11 ключевое слово auto приобрело новое значение. Поэтому, хотя a в C имеет тип int, хранящийся в месте AUTOmatic, он имеет тип char в C ++ 11.

РЕДАКТИРОВАТЬ: Как FUZxxl сказал неявный int был удален в C11.


1
Не работает с C11, так как C11 удалил неявное intправило.
FUZxxl

@FUZxxl Спасибо, я исправил свой пост.
Феликс Бытов

1

Программа с самоописанием

Это напечатает "Эта программа написана на C!" если скомпилирован с использованием компилятора C; в противном случае будет напечатано «Эта программа написана на C ++!». Требуется компилятор 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;}

Большинство других сообщений используют разницу в размере символа в C против C ++; этот использует тот факт, что в C99 trueопределяется как число. Это вставит восклицательный знак и нулевой терминатор в зависимости от размера true.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.