Напишіть поліглот 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 ++, зокрема, способом поводження з літерами char. У C вони розглядаються як цілі числа, тому sizeof('!')повертає 4, на відміну від 1 у C ++. ((...+1)&1)Частина є лише частиною простий операції побітового , який буде повертати 1 , якщо sizeof('!')повертає 4, і 0 , якщо вона повертає 1. Це в результаті чого число множиться на цілих чисел в масиві , tа потім , що продукт , нарешті , додають до специфічний характер трансформується. У C ++ продукт завжди буде нульовим, тому рядок C++ rules!залишається незмінною. У C продукт завжди буде значенням у t, і тому рядок змінюється на C++ stinks.


5
Я впевнений, що це щось обдурення ...
Бета-розпад

@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

Просто кілька булів

#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
malat

8
@malat Так, і саме цей факт використовується в цьому рішенні. Для c ++ функцією є int test (bool / * неназваний булевий аргумент * /); а для C він використовує декларацію int за замовчуванням, що означає int test (int bool); тому "bool" - це ім'я цілочисельної змінної.
Qwertiy

5

Я міг би це зробити за допомогою 3-х рядкової програми, але тоді було б очевидно, чому це дає різні результати для 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 in C має тип int, який зберігається в AUTOmatic, він має тип char в C ++ 11.

EDIT: Як сказав FUZxxl, неявний int був видалений у C11.


1
Не працює з C11, оскільки C11 видалив неявне intправило.
FUZxxl

@FUZxxl Дякую, я відкоригував свою посаду.
Фелікс Байтов

1

Самоописуюча програма

Це надрукує "Ця програма написана на С!" якщо складено за допомогою компілятора С; в іншому випадку він надрукує "Ця програма написана на 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.