Viết một Polyglot C / C ++


27

Khái niệm thử thách này khá đơn giản. Tất cả bạn phải làm là viết một chương trình sẽ biên dịch thành cả C hợp lệ và C ++ hợp lệ! Vâng, có một số sản phẩm khai thác. Chương trình phải hành xử khác nhau khi được biên dịch trong mỗi ngôn ngữ. Chương trình phải có đầu ra khác nhau cho mỗi ngôn ngữ để được coi là "hành xử khác nhau".

Quy tắc

  • Chương trình phải có cả C và C ++ hợp lệ
  • Chương trình phải có các đầu ra khác nhau dựa trên ngôn ngữ được biên dịch.
  • #ifdef __cplusplushoặc các thủ thuật tiền xử lý "dễ dàng" khác không được khuyến khích! (Tuy nhiên, các hoạt động tiền xử lý khác là hoàn toàn tốt.)
  • Cố gắng không làm cho nó trông hoàn toàn rõ ràng rằng chương trình làm một cái gì đó khác nhau.

Đây là một , vì vậy ai có giải pháp thú vị và đáng ngạc nhiên nhất sẽ chiến thắng. Chúc vui vẻ!

Thí dụ:

Tôi đã tạo chương trình của riêng mình để xem liệu điều này thậm chí có thể thực hiện được với các #ifdefthủ thuật không:

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

Chương trình này xuất ra C++ rules!khi được biên dịch trong C ++ và C++ stinkskhi được biên dịch trong C.

Giải trình:

Điều gây ra sự khác biệt giữa các ngôn ngữ là tr()chức năng. Nó tận dụng một trong những khác biệt giữa C và C ++, cụ thể là cách xử lý chữ char. Trong C, chúng được coi là số nguyên, vì vậy sizeof('!')trả về 4, trái ngược với 1 trong C ++. Phần ((...+1)&1)này chỉ là một phần của thao tác bitwise đơn giản sẽ trả về 1 nếu sizeof('!')trả về 4 và 0 nếu trả về 1. Số kết quả đó được nhân với số nguyên trong mảng tvà sau đó sản phẩm đó cuối cùng được thêm vào ký tự cụ thể được chuyển đổi. Trong C ++, sản phẩm sẽ luôn bằng 0, do đó chuỗi C++ rules!vẫn không thay đổi. Trong C, sản phẩm sẽ luôn là giá trị trong tvà do đó chuỗi thay đổi thành C++ stinks.


5
Tôi chắc chắn đây là bản sao của một cái gì đó ...
Beta Decay

@BetaDecay phải không? Tôi đã cố gắng tìm kiếm một cái gì đó tương tự và tôi không thể tìm thấy bất cứ điều gì.
Mewy

Bạn có thể giải thích làm thế nào chương trình của bạn hoạt động khác nhau (nếu nó không làm hỏng thách thức)?
AL

@AL Tôi đã chỉnh sửa trong một lời giải thích cho bài viết của tôi.
Mewy

Tất cả những cái từ stackoverflow.com/questions/2038200/ Có thể được sử dụng ở đây - với một chút xáo trộn.
Jerry Jeremiah

Câu trả lời:


18

Là một chiếc bánh nói dối?

Vì đã có nhiều tranh luận về việc chiếc bánh có phải hay không nói dối, tôi đã viết chương trình này để trả lời câu hỏi gây tranh cãi này.

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

Kết quả sẽ ra sao?

C:

The cake is ..not a lie?

C ++:

The cake is a LIE!


1
Điều này. Tôi thích điều này.
FUZxxl

9

Chỉ là vài cái ghế

#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 không phải là một phần của C89
malat

8
@malat Yep, và chính xác thực tế này được sử dụng trong giải pháp này. Đối với c ++, hàm là int test (bool / * đối số boolean không tên * /); và đối với C, nó sử dụng khai báo int mặc định có nghĩa là int test (int bool); vì vậy 'bool' là tên của biến số nguyên.
Qwertiy

5

Tôi có thể đã làm điều này với một chương trình 3 dòng nhưng sau đó rõ ràng là tại sao nó tạo ra kết quả khác nhau cho C và C ++. Vì vậy, thay vào đó tôi bắt đầu viết một chương trình lớn hơn với một số bản sao có kết quả khác nhau trong C và 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;
}

Bạn cần chỉ định một dòng lệnh. Khi tôi chạy nó trên bản sao của gcc, tôi nhận được kết quả này:

>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

Làm thế nào mọi thứ có thể đi sai lầm khủng khiếp như vậy?


Mặc dù những người khác đã làm điều tương tự, bạn che giấu nó khá tốt.
kirbyfan64sos

5
#include <stdio.h>

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

4

Cái này hoạt động với C ++ 11 và mới hơn và bất kỳ C nào cho đến nay (trước C11).

#include <stdio.h>

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

Xem tại đây: C ++: http://ideone.com/9Gkg75 và C: http://ideone.com/eECSmr

Nó khai thác thực tế là trong C ++ 11, từ khóa tự động có một ý nghĩa mới. Vì vậy, trong khi a in C thuộc kiểu int được lưu trữ ở vị trí AUTOmatic thì nó thuộc kiểu char trong C ++ 11.

EDIT: Như FUZxxl đã nói int ẩn đã bị xóa trong C11.


1
Không hoạt động với C11 vì C11 đã loại bỏ intquy tắc ngầm .
FUZxxl

@FUZxxl Cảm ơn, tôi đã điều chỉnh bài viết của mình.
Felix Bytow

1

Chương trình tự mô tả

Điều này sẽ in "Chương trình này được viết bằng C!" nếu được biên dịch bằng trình biên dịch C; nếu không, nó sẽ in "Chương trình này được viết bằng C ++!". Nó cần một trình biên dịch 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;}

Hầu hết các bài đăng khác đều tận dụng sự khác biệt về kích thước của một char trong C so với C ++; cái này sử dụng thực tế là, trong C99, trueđược định nghĩa là một số. Điều này chèn dấu chấm than và dấu chấm hết null dựa trên kích thước của true.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.