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でコンパイルされたときに出力C++ stinksされます。

説明:

言語間の違いを引き起こすのはtr()関数です。CとC ++の違いの1つ、特にcharリテラルの処理方法を利用します。Cでは、整数として扱われるためsizeof('!')、C ++の1ではなく4を返します。この((...+1)&1)部分はsizeof('!')、4を返す場合は1を返し、1を返す場合は0を返す単純なビット演算の一部にすぎません。その結果の数値に配列内のintが乗算され、t最終的に変換される特定の文字にその積が追加されます。C ++では、製品は常にゼロになるため、文字列C++ rules!は変更されません。Cでは、製品は常にの値になるtため、文字列はに変わりますC++ stinks


5
私は...確か、これは何かのだまされやすい人ですよ
ベータ崩壊

@BetaDecayですか?似たようなものを探してみましたが、何も見つかりませんでした。
Mewy 14年

プログラムがどのように異なる動作をするのか説明していただけますか(チャレンジが損なわれない場合)
AL

@AL投稿の説明で編集しました。
Mewy 14年

stackoverflow.com/questions/2038200/…のすべてのものをここで使用できます-少し難読化してください。
ジェリージェレミア14年

回答:


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


ブール値は、C89の一部ではありません
malat

8
@malatはい、まさにこの事実がこのソリューションで使用されています。C ++の場合、関数はint test(bool / * unnamed boolean argument * /); Cでは、int test(int bool)を意味するデフォルトのint宣言を使用します。したがって、「bool」は整数変数の名前です。
Qwertiy 14年

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

5
#include <stdio.h>

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

4

これは、C ++ 11以降およびこれまでの(C11より前の)Cで動作します。

#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キーワードが新しい意味を得たという事実を利用します。したがって、CのaはAUTOmaticの場所に格納されているint型ですが、C ++ 11ではchar型です。

編集:FUZxxlが言ったように、暗黙のintはC11で削除されました。


1
C11は暗黙のintルールを削除したため、C11では機能しません。
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ます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.