Tulis C / C ++ Polyglot

27

Konsep tantangan ini cukup sederhana. Yang harus Anda lakukan adalah menulis program yang akan dikompilasi sebagai C yang valid dan C ++ yang valid! Ya, ada beberapa tangkapan. Program harus berperilaku berbeda saat dikompilasi dalam setiap bahasa. Program harus memiliki keluaran yang berbeda untuk setiap bahasa agar dianggap "berperilaku berbeda".

Aturan

  • Program harus C dan C ++ yang valid
  • Program harus memiliki keluaran yang berbeda berdasarkan bahasa yang dikompilasi.
  • #ifdef __cplusplusatau trik preprosesor "mudah" lainnya tidak disarankan! (Namun, operasi preprosesor lainnya baik-baik saja.)
  • Cobalah untuk tidak membuatnya terlihat jelas bahwa program melakukan sesuatu yang berbeda.

Ini adalah , jadi siapa pun yang memiliki solusi paling menarik dan mengejutkan akan menang. Selamat bersenang-senang!

Contoh:

Saya membuat program saya sendiri untuk melihat apakah ini bahkan mungkin dilakukan dengan #ifdeftrik:

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

Output program ini C++ rules!ketika dikompilasi dalam C ++ dan C++ stinksketika dikompilasi dalam C.

Penjelasan:

Apa yang menyebabkan perbedaan antar bahasa adalah tr()fungsinya. Itu mengambil keuntungan dari salah satu perbedaan antara C dan C ++, khususnya, bagaimana literal char diperlakukan. Dalam C, mereka diperlakukan sebagai bilangan bulat, jadi sizeof('!')mengembalikan 4, yang bertentangan dengan 1 di C ++. Bagian ((...+1)&1)ini hanya bagian dari operasi bitwise sederhana yang akan mengembalikan 1 jika sizeof('!')mengembalikan 4, dan 0 jika mengembalikan 1. Angka yang dihasilkan dikalikan dengan int dalam array tdan kemudian produk itu akhirnya ditambahkan ke karakter spesifik yang sedang diubah. Dalam C ++ produk akan selalu nol, sehingga string C++ rules!tetap tidak berubah. Dalam C, produk akan selalu menjadi nilai t, dan string berubah menjadi C++ stinks.

Mewy
sumber
5
Saya yakin ini adalah penipuan sesuatu ...
Beta Decay
@ BetaDecay Benarkah? Saya mencoba mencari sesuatu yang serupa dan saya tidak dapat menemukan apa pun.
Mewy
Bisakah Anda jelaskan bagaimana program Anda bekerja secara berbeda (jika tidak merusak tantangan)?
AL
@AL Saya mengedit penjelasan untuk posting saya.
Mewy
Semua yang dari stackoverflow.com/questions/2038200/… dapat digunakan di sini - dengan sedikit kebingungan.
Jerry Jeremiah

Jawaban:

18

Apakah kue itu bohong?

Karena ada banyak perdebatan tentang apakah kue itu bohong atau tidak, saya menulis program ini untuk menjawab pertanyaan yang kontroversial ini.

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

Apa hasilnya nanti?

C:

The cake is ..not a lie?

C ++:

The cake is a LIE!

es1024
sumber
1
Ini. Saya suka ini.
FUZxxl
9

Hanya beberapa 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

Qwertiy
sumber
bool bukan bagian dari C89
malat
8
@malat Yap, dan sebenarnya fakta ini digunakan dalam solusi ini. Untuk c ++ fungsinya adalah tes int (bool / * argumen boolean tanpa nama * /); dan untuk C menggunakan deklarasi int default yang berarti pengujian int (int bool); jadi 'bool' adalah nama variabel integer.
Qwertiy
5

Saya bisa melakukan ini dengan program 3 baris tetapi kemudian akan menjadi jelas mengapa menghasilkan hasil yang berbeda untuk C dan C ++. Jadi alih-alih saya mulai menulis program yang lebih besar dengan beberapa stegonografi yang mendapat hasil berbeda dalam C dan 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;
}

Anda perlu menentukan baris perintah. Ketika saya menjalankannya pada salinan gcc saya, saya mendapatkan hasil ini:

>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

Bagaimana hal-hal buruk bisa terjadi?

Jerry Jeremiah
sumber
Meskipun orang lain melakukan hal yang sama, Anda menutupinya dengan cukup baik.
kirbyfan64sos
5
#include <stdio.h>

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

Yang ini bekerja dengan C ++ 11 dan yang lebih baru dan C apa pun sejauh ini (sebelum C11).

#include <stdio.h>

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

Lihat di sini: C ++: http://ideone.com/9Gkg75 dan C: http://ideone.com/eECSmr

Itu mengeksploitasi fakta bahwa dalam C ++ 11 kata kunci otomatis mendapat makna baru. Jadi, sementara di C adalah tipe int disimpan di lokasi OTOMATIS itu adalah tipe char di C ++ 11.

EDIT: Seperti yang dikatakan FUZxxl int implisit telah dihapus di C11.

Felix Bytow
sumber
1
Tidak berfungsi dengan C11 karena C11 telah menghapus intaturan implisit .
FUZxxl
@ FuZxxl Terima kasih, saya menyesuaikan posting saya.
Felix Bytow
1

Program yang menggambarkan diri sendiri

Ini akan mencetak "Program ini ditulis dalam bahasa C!" jika dikompilasi menggunakan kompiler C; jika tidak, itu akan mencetak "Program ini ditulis dalam C ++!". Perlu kompiler 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;}

Sebagian besar posting lain memanfaatkan perbedaan ukuran char di C vs C ++; ini menggunakan fakta bahwa, dalam C99, truedidefinisikan sebagai angka. Ini memasukkan tanda seru dan terminator nol berdasarkan ukuran true.

kirbyfan64sos
sumber