Bir C / C ++ Polyglot yazın


27

Bu zorluğun konsepti oldukça basittir. Yapmanız gereken tek şey hem geçerli C hem de geçerli C ++ olarak derleyecek bir program yazmak! Eh, bazı yakalamalar var. Program her dilde derlendiğinde farklı davranmalıdır. Program, “farklı davranmak” olarak değerlendirilmek için her dil için farklı çıktılara sahip olmalıdır.

kurallar

  • Program geçerli C ve C ++ olmalı
  • Program, derlendiği dile göre farklı çıktılara sahip olmalıdır.
  • #ifdef __cplusplusveya diğer "kolay" önişlemci numaralar önerilmez! (Diğer önişlemci işlemleri olsa da gayet iyi.)
  • Programın farklı bir şey yaptığını tamamen açık göstermemeye çalışın.

Bu bir , bu nedenle en ilginç ve şaşırtıcı çözümü olan kim kazanır. İyi eğlenceler!

Örnek:

Bunun #ifdefpüf noktaları ile yapılmasının mümkün olup olmadığını görmek için kendi programımı oluşturdum :

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

Bu program C++ rules!C ++ 'da ve C' C++ stinksde derlendiğinde çıktı verir.

Açıklama:

Diller arasındaki farka neden olan tr()fonksiyondur. C ve C ++ arasındaki farklardan bir tanesinden, özellikle char değişmezlerine nasıl davranıldığından faydalanır. C'de, tamsayı olarak değerlendirilir, bu nedenle sizeof('!')C ++ 'da 1 yerine 4 döndürür. ((...+1)&1)Eğer bölümü 1 dönmek basit bir bit-bazında işlemin sadece bir parçası sizeof('!')döner 4 ve 0 numarayı olarak dizide ints ile çarpılır bu 1. dönerse türün son olarak belirli bir karakter dönüştürülmüş olan ilave edilmesidir ve daha sonra. C ++ 'da ürün daima sıfır olacaktır, bu yüzden dizi C++ rules!değişmeden kalır. C'de, ürün her zaman değeri olacaktır tve bu nedenle dize değişir C++ stinks.


5
Eminim ki bu bir şeylerdir ...
Beta Çürüğü

@ BetaDecay Öyle mi? Benzer bir şey aramaya çalıştım ve hiçbir şey bulamadım.
Mewy

Lütfen programınızın nasıl farklı çalıştığını açıklayabilir misiniz (zorluğu bozmazsa)?
AL

@ AL Bir yazımda yayınım için bir düzenleme yaptım.
Mewy

Bütün olanları stackoverflow.com/questions/2038200/... burada kullanılabilecek - Biraz şaşırtmaca ile.
Jerry Jeremiah

Yanıtlar:


18

Pasta yalan mı?

Pastanın yalan olup olmadığı konusunda çok fazla tartışma olduğu için bu tartışmalı soruyu cevaplamak için bu programı yazdım.

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

Sonuç ne olacak?

C:

The cake is ..not a lie?

C ++:

The cake is a LIE!


1
Bu. Bunu severim.
FUZxxl

9

Sadece bazı havuzlar

#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’un bir parçası değil
malat

8
@ Malat Yep, bu çözümde tam olarak bu gerçeği kullanıyor. C ++ için işlev int testidir (bool / * adsız boolean argümanı * /); ve C için int testi (int bool) anlamına gelen varsayılan int bildirimini kullanır; bu yüzden 'bool' tamsayı değişkeninin adıdır.
Qwertiy

5

Bunu 3 satırlık bir programla yapabilirdim, ancak C ve C ++ için neden farklı sonuçlar ürettiği açıktı. Bunun yerine C ve C ++ 'da farklı sonuçlar alan bir stegonografiyle daha büyük bir program yazmaya başladım ...

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

Bir komut satırı belirtmeniz gerekiyor. Gcc kopyasında çalıştırdığımda bu çıktıyı alıyorum:

>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

İşler nasıl bu kadar korkunç bir şekilde yanlış gidebilir?


Diğerleri de aynı şeyi yapmış olsa da, onu oldukça iyi gizlediniz.
kirbyfan64sos

5
#include <stdio.h>

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

4

Bu, C ++ 11 ve daha yeni ve şu ana kadar herhangi bir C ile çalışıyor (C11'den önce).

#include <stdio.h>

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

Buraya bakın: C ++: http://ideone.com/9Gkg75 ve C: http://ideone.com/eECSmr

C ++ 11'de auto anahtar sözcüğünün yeni bir anlamı olduğu gerçeğini kullanıyor. Bu nedenle, bir C in bir AUTOmatic konumunda saklanan int türünde iken, C ++ 11 de char türündedir.

EDIT: FUZxxl’in söylediği gibi, int int C11’de kaldırıldı.


1
C11 örtük intkuralı kaldırdığından, C11 ile çalışmaz .
FUZxxl

@ FUZxxl Teşekkürler, mesajımı değiştirdim.
Felix Bytow

1

Kendi kendini tanımlayan program

Bu yazdıracak "Bu program C ile yazılmıştır!" bir C derleyicisi kullanılarak derlenmişse; Aksi takdirde, "Bu program C ++! 'da yazılmıştır. Bir C99 derleyicisine ihtiyacı var.

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

Diğer mesajların çoğu, C + C ++ 'daki karakter büyüklüğünün farkından yararlanır; bu, C99'da truebir sayı olarak tanımlandığı gerçeğini kullanır . Bu, ünlemenin büyüklüğüne bağlı olarak ünlem işaretini ve boş sonlandırıcıyı ekler true.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.