【问题标题】:Write a program that will print "C" if compiled as an (ANSI) C program, and "C++" if compiled as a C++ program编写一个程序,如果编译为 (ANSI) C 程序将打印“C”,如果编译为 C++ 程序将打印“C++”
【发布时间】:2011-01-03 12:53:48
【问题描述】:

取自http://www.ocf.berkeley.edu/~wwu/riddles/cs.shtml

它看起来非常适合我的编译器。不知道去哪里找?

【问题讨论】:

    标签: c++ c compiler-specific


    【解决方案1】:

    1。滥用C++自动typedefs

    (请注意,struct 需要在内部范围内声明,以便在 C++ 中优先于外部名称。)

    #include <stdio.h>
    
    int main(void)
    {
        char x;
    
        {
            struct x { char dummy[2]; };
            printf("%s\n", sizeof (x) == 1 ? "C" : "C++");
        }
    }
    

    不依赖于sizeof (type)sizeof (variable) 之间歧义的类似版本,仅使用类型:

    #include <stdio.h>
    
    int main(void)
    {
        typedef char t;
    
        {
            struct t { char dummy[2]; };
            printf("%s\n", sizeof (t) == 1 ? "C" : "C++");
        }
    }
    

    2。滥用C++struct/class等价,自动typedefs,自动生成默认构造函数

    #include <stdio.h>
    
    int isC = 0;
    void Foo() { isC = 1; }
    
    int main(void)
    {
        struct Foo { int dummy; };
        Foo();
        printf("%s\n", isC ? "C" : "C++");
    }
    

    3。在 C 中滥用嵌套的 struct 声明

    另见Symbol clashing of inner and outer structs, C++ vs C

    #include <stdio.h>
    
    int main(void)
    {
        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。虐//cmets

    这不适用于 C99 或支持 // 作为扩展的 C89 编译器。

    #include <stdio.h>
    
    int main(void)
    {
        printf("%s\n",
               0 //* */
               +1
               ? "C++"
               : "C");
    }
    

    或者:

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

    5。 sizeofchar 文字的区别

    请注意,这不能保证可移植,因为某些假设平台可能使用超过 8 位的字节,在这种情况下 sizeof(char) 可能与 sizeof(int) 相同。 (另见Can sizeof(int) ever be 1 on a hosted implementation?

    #include <stdio.h>
    
    int main(void)
    {
        printf("%s\n", sizeof 'a' == 1 ? "C++" : "C");
    }
    

    6。执行左值⇒右值转换时的滥用差异

    这是基于 ISO C++03 标准中的 5.16、5.17、5.18 示例,它适用于 gcc,但不适用于 MSVC(可能是由于编译器错误?)。

    #include <stdio.h>
    
    int main(void)
    {
        void* array[2];
        printf("%s\n",
               (sizeof (((void) 0), array) / sizeof (void*) == 1)
               ? "C"
               : "C++");
    }
    

    7。滥用 C 和 C++ 的语法解析三元运算符的方式差异

    这不是严格合法的,但有些编译器是松懈的。

    #include <stdio.h>
    
    int main(void)
    {
        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

    【讨论】:

    • 我很确定标准要求 char 为 1 字节,字节为 8 位。
    • 不,char 根据定义是 1 个字节,一个字节必须至少 8 位,但可以更多。这就是CHAR_BIT 存在的原因。
    • 要求 char 为 1 个字节。一个字节中的位数是实现定义的。
    • +1。一定会喜欢一个选项是不可移植的,而其他六个被描述为滥用的答案:-)
    • @jacques struct x { ... } 是在 C 中声明 struct 类型为 struct x 的典型方式。如果你想要一个typedef,那么你在使用它时不需要一直输入struct,你会做typedef struct x { ... } simpler_name。请注意,struct tag (x) 和 typedef (simpler_name) 位于不同的 C 命名空间中,因此您也可以使用 typedef struct x { ... } x。 C++ 为structclass 隐式创建了这样的typedefs,因此方法#1 中的x 在C++ 中的解析方式与在C 中的解析方式不同。
    【解决方案2】:

    我们不得不在学校做类似的作业。我们不允许使用预处理器(当然#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");
    }
    

    【讨论】:

    • 在 C++ 中它们不形成单独的命名空间是不正确的,它们被编译器分开,但是编译器会在 both 命名空间(首先是非用户定义类型,然后是用户定义类型)。有几种测试方法,其中最简单的是typedef struct X {} Y; void X(); 编译,但是如果你添加void Y(); 你会得到一个编译器错误:符号Y,在非用户定义的命名空间中已经使用由typedef.
    【解决方案3】:

    足够简单。

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

    或者在没有官方标准的情况下是否需要这样做?

    【讨论】:

    • 刚刚使输出与问题一致。
    • 没错。 C++ 1998 标准说:“在编译 C++ 翻译单元时,名称 __cplusplus 被定义为值 199711L”。 (第 16.8 节:[cpp.predefined]
    • 当然,一个非常讨厌的 C 实现可以定义 __cplusplus。
    • __cplusplus 被定义为 199711L 仅当编译器完全符合。例如,gcc 仍然将 __cplusplus 定义为 1。
    • @Neil,在 C99 标准中,第 6.10.8.5 节明确禁止实现定义 __cplusplus。但在 C89 中没有这种情况。
    【解决方案4】:
    puts(sizeof('a') == sizeof(int) ? "C" : "C++");
    

    【讨论】:

    • 这实际上并不能保证有效。如果CHAR_BIT 至少为 16,sizeof(int) 可以为 1。
    • Oak,在 C 中,字符文字的类型为 int,在 C++ 中,它们的类型为 char
    【解决方案5】:

    这是程序:

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

    here 是关于 C 和 C++ 差异的一些不错的读物。

    【讨论】:

      【解决方案6】:

      看看是否定义了__STDC____cplusplus 编译器宏。

      【讨论】:

        【解决方案7】:

        一个字,__cplusplus

        【讨论】:

          【解决方案8】:

          我猜测其目的是编写取决于语言本身之间差异的东西,而不仅仅是预定义的宏。虽然从技术上讲不能绝对保证它可以工作,但这样的事情可能更接近于期望:

          int main() { 
              char *names[] = { "C", "C++"};
          
              printf("%s\n", names[sizeof(char)==sizeof('C')]);
              return 0;
          }
          

          【讨论】:

          • 和 Matthew Slattery 一样的咆哮,这可能不适用于所有平台。
          • @avakar:理论上有点正确——这就是我说它不能绝对保证工作的原因。同时,C I/O 库的基本设计依赖于 EOF 不同于 unsigned char 的任何值。这意味着 sizeof(int)>sizeof(unsigned char)。尽管有一个想法应该允许 sizeof(char)==sizeof(int) ,但让 C 以这种方式工作确实是不可能的,所以上面的代码确实可以可靠地工作。
          • 不要将sizeof 的结果与类型允许的值范围混淆。
          • @avakar 是正确的,因为这不能保证有效:可能有sizeof(int) == 1 并且所有int 值都是来自getchar() 的有效字符返回,在这种情况下@987654326 @ 也可以是有效字符,测试EOF 是否表示文件结束需要用feof() 执行(并用ferror() 测试错误)。 Crays 是sizeof(int) == 1 的一个例子:它们曾经让所有整数类型都是 64 位宽。
          • @jlk:就像我说的,理论上,这是正确的。实际上,与 int 大小相同的实现字符会破坏这么多没人会使用它的代码。就 Crays 而言,所有整数类型都具有相同大小的想法是一个都市传说——尽管反复测试表明,如果它是真的,它仍然是一个谣言,尽管它是真的,它只是使用一个从未发布到外部世界(也没有证据表明它曾经存在于内部)。
          【解决方案9】:

          对于它的价值,这是另一个答案:

          char x[sizeof(char *)+2], y[1];
          printf("%.*s\n", sizeof(1?x:y)-sizeof(char *)+1, "C++");
          

          【讨论】:

          • 我尝试使用 gcc 和 g++ 编译以下代码 pastebin.com/zsxX1NNN 文件分别保存为 foo.c 和 foo.cpp。它两次打印 C。我不认为你这样做的方式应该有效,因为指针的大小取决于架构。
          • 也许我的想法是错误的。我认为在这种情况下,数组不会衰减为 C++ 中的指针...
          【解决方案10】:

          您可以尝试预处理器指令,但这可能不是他们想要的。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-07-23
            • 2017-03-04
            • 1970-01-01
            • 2018-05-10
            • 1970-01-01
            • 2022-07-09
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多