Напишите программу, которая будет печатать «C», если она скомпилирована как (ANSI) C-программу, и «C ++», если она скомпилирована как программа C ++. - PullRequest
15 голосов
/ 10 января 2010

взято с http://www.ocf.berkeley.edu/~wwu/riddles/cs.shtml

Это выглядит очень специфично для компилятора. Не знаете, где искать?

Ответы [ 10 ]

41 голосов
/ 10 января 2010

Мы должны были сделать подобное задание в школе. Нам не разрешалось использовать препроцессор (кроме #include, конечно). В следующем коде используется тот факт, что в C имена типов и имена структур образуют отдельные пространства имен, тогда как в C ++ это не так.

#include <stdio.h>
typedef int X;
int main()
{
    struct X { int ch[2]; };
    if (sizeof(X) != sizeof(struct X))
        printf("C\n");
    else
        printf("C++\n");
}
40 голосов
/ 10 января 2010

Мне известно 7 подходов:

1. Злоупотребление C ++ автоматическое typedef s

(Обратите внимание, что структура должна быть объявлена ​​во внутренней области видимости, чтобы она имела приоритет над внешним именем в C ++.)

char x;
{
    struct x { char dummy[2]; };
    printf("%s\n", sizeof (x) == 1 ? "C" : "C++");
}

Аналогичная версия, которая не зависит от неоднозначности между sizeof (type) и sizeof (variable), используя только типы:

typedef char t;
{
    struct t { char dummy[2]; };
    printf("%s\n", sizeof (t) == 1 ? "C" : "C++");
}

2. Злоупотребление C ++ struct / class эквивалентность, автоматическое typedef s и автоматически сгенерированные конструкторы по умолчанию

/* Global*/
int isC = 0;
void Foo() { isC = 1; }

/* In some function */
struct Foo { int dummy; };
Foo();
printf("%s\n", isC ? "C" : "C++");

3. Злоупотребление вложенными struct объявлениями в C

Также см. Столкновение символов внутренних и внешних структур, C ++ и C

typedef struct inner { int dummy; } t;
{
    struct outer { struct inner { t dummy[2]; } dummy; };
    printf("%s\n",
           sizeof (struct inner) == sizeof (t)
           ? "C++"
           : "C");
}

4. Злоупотребление // комментарии

Это не будет работать с C99 или с компиляторами C89, которые поддерживают // как расширение.

printf("%s\n",
       0 //* */
       +1
       ? "C++"
       : "C");

или альтернативно:

printf("s\n",
       1 //* */ 2
       ? "C++"
       : "C");

5. sizeof различия с char литералами

Обратите внимание, что это не гарантируется переносимость, поскольку возможно, что некоторая гипотетическая платформа может использовать байты с более чем 8 битами, в этом случае sizeof(char) может совпадать с sizeof(int). (Также см. Может ли sizeof (int) когда-либо быть 1 в размещенной реализации? )

printf("%s\n", sizeof 'a' == 1 ? "C++" : "C");

6. Различия в злоупотреблении при выполнении преобразования lvalue & rArr; rvalue

Это основано на примере 5.16, 5.17, 5.18 в стандарте ISO C ++ 03 и работает в gcc, но не в MSVC (возможно, из-за ошибки компилятора?).

void* array[2];
printf("%s\n",
       (sizeof (((void) 0), array) / sizeof (void*) == 1)
       ? "C"
       : "C++");

7. Злоупотребление различиями в том, как грамматики C и C ++ анализируют троичный оператор

Этот код не является строго законным, но некоторые компиляторы слабы.

int isCPP = 1;
printf("%s\n", (1 ? isCPP : isCPP = 0) ? "C++" : "C");

(Вы также можете проверить наличие макроса препроцессора __cplusplus (или различных других макросов), но я думаю, что это не соответствует духу вопроса.)

У меня есть реализации для всего этого по адресу: http://www.taenarum.com/csua/fun-with-c/c-or-cpp.c

30 голосов
/ 10 января 2010

Достаточно просто.

#include <stdio.h>
int main(int argc, char ** argv) {
#ifdef __cplusplus
printf("C++\n");
#else
printf("C\n");
#endif
return 0;
}

Или есть требование сделать это без официального стандарта?

15 голосов
/ 10 января 2010
puts(sizeof('a') == sizeof(int) ? "C" : "C++");
3 голосов
/ 10 января 2010

Вот программа:

#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("This is %s\n", sizeof 'a' == sizeof(char) ? "C++" : "C");
    return 0;
}

И здесь - отличное прочтение различий между Си и Си ++.

2 голосов
/ 10 января 2010

Просто посмотрите, определены ли макросы компилятора __STDC__ и __cplusplus.

1 голос
/ 10 января 2010

Я предполагаю, что целью является написать что-то, что зависит от различий между самими языками, а не только от предопределенных макросов. Хотя технически это не совсем гарантирует работу, что-то вроде этого, вероятно, ближе к желаемому:

int main() { 
    char *names[] = { "C", "C++"};

    printf("%s\n", names[sizeof(char)==sizeof('C')]);
    return 0;
}
1 голос
/ 10 января 2010

Одно слово, __cplusplus.

0 голосов
/ 25 июня 2011

Для чего это стоит, вот другой ответ:

char x[sizeof(char *)+2], y[1];
printf("%.*s\n", sizeof(1?x:y)-sizeof(char *)+1, "C++");
0 голосов
/ 10 января 2010

Вы можете попробовать директивы препроцессора, но это может быть не то, что они ищут.

...