Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C预处理器作为语言创建工具的长度/限制是什么?我在哪里可以了解更多关于这些的信息?_C++_C_C Preprocessor_Language Design - Fatal编程技术网

C++ C预处理器作为语言创建工具的长度/限制是什么?我在哪里可以了解更多关于这些的信息?

C++ C预处理器作为语言创建工具的长度/限制是什么?我在哪里可以了解更多关于这些的信息?,c++,c,c-preprocessor,language-design,C++,C,C Preprocessor,Language Design,比亚恩·斯特劳斯特鲁普在他的报告中说: < p>构建cFAc++,第一个C++ 我第一次用C写了一个 “带类的C”-到C预处理器。“C “带类”是一种C方言 成为C++的直接祖先… 然后我写了第一个版本的 “C与类”中的C前面 当我读到这篇文章时,它激起了我对C预处理器的兴趣。我认为它的宏功能适合于简化常见表达式,但没有想到它能够在我想象的将类引入C所需要的级别上显著增加语法和语义 现在我有一些问题想问: 有没有这种方法的其他例子可以从C引导语言 Stroustrup原创作品的来源是否随处可见

比亚恩·斯特劳斯特鲁普在他的报告中说:

< p>构建cFAc++,第一个C++ 我第一次用C写了一个 “带类的C”-到C预处理器。“C “带类”是一种C方言 成为C++的直接祖先… 然后我写了第一个版本的 “C与类”中的C前面

当我读到这篇文章时,它激起了我对C预处理器的兴趣。我认为它的宏功能适合于简化常见表达式,但没有想到它能够在我想象的将类引入C所需要的级别上显著增加语法和语义

现在我有一些问题想问:

  • 有没有这种方法的其他例子可以从C引导语言

  • Stroustrup原创作品的来源是否随处可见

  • 我在哪里可以了解更多关于使用此技术的细节

  • 该方法的长度/限制是什么?比如说,有人能创建一组预处理器宏,让人们用Lisp/Scheme之类的语言编写代码吗


  • 请注意,Stroustrup并不是说他使用C预处理器(cpp)来创建带有类的C,他没有这样做。他用C编写了自己的预处理器,而Cfront是一个真正的编译器,根本不是预处理器。事实上,C预处理器非常不适合语言开发,因为它没有任何解析能力。

    C预处理器不是您想要的。它不能像Cfront那样添加语法和语义

    cFrand是一个实际编译器,它用C类,后来的C++,C,C,它是一个预处理器,它是在C编译器之前运行的。我曾经使用一个名为f2c的程序将FORTRAN 77代码翻译成C代码。它的工作原理是一样的

    有像Common Lisp这样的语言有足够的宏能力来添加新的语法和语义,还有像Forth这样的语言,它们的系统足够灵活来适应变化,但这对大多数语言都不起作用。

    听起来他的“带类的C”-to-C预处理器与标准C预处理器不同,因为他特别提到自己编写这个预处理器


    C预处理器非常有限。它可以用来简写常用的表达,但仅此而已。当你试图用它来定义新的语言结构时,它会很快变得更加繁琐和脆弱。

    我认为Objective-C也是这样开始的。它是一个预处理器,它构建了一些C代码,然后将这些代码传递给C编译器。但它不是
    #define FOO
    意义上的C预处理器,而是在标准C预处理器之前或之后作为附加步骤运行的。然后,可以将任何数量的预处理器步骤的结果发送到C编译器。

    有关可以使用C预处理器创建的“语言”的畸形类型的示例,请查看以下头文件:

    它来自史蒂夫·伯恩(Steve Bourne)编写的原始Unix shell的源代码,旨在将C语言转变为类似Algol的语言。下面是使用一段代码时的外观示例:

    这看起来有点奇怪,但它仍然是C。它可能看起来像一种不同的语言,但因为它是在预处理器中实现的,所以没有语法支持

    WHILE foo
    DO
        SWITCH
        ....
        ENDSW
    OD
    
    都很好,编译得很好,但也很好

    WHILE foo
    DO
        SWITCH
        ....
        OD
    ENDSW
    

    其他人提到的,C++不是用C预处理器(CPP)创建的。 也就是说,你可以用CPP和递归做一些疯狂的事情;我很漂亮 当然是图灵完成了。我将要链接的库使用了很多 为了获得有趣的行为而耍的丑陋的把戏。虽然你可以建立一种 优雅在顶部,许多人可能认为它是。 想更温和地介绍一下这种东西,试试看

    要深入了解,请查看

    • ——“跨平台”,但更丑陋;部分流行的C++库
    • --由Boost pp guy跟进,但只支持C99兼容工具,因此更加优雅
    • --据我所知,这是一种类似Lisp的语言,受混沌的启发,建立在纯CPP的基础上

    例如,对于顺序或混沌,您可以用纯CPP编写递归斐波那契序列生成器

    我建议您从开始,它提供了许多关于C预处理器的GCC实现的有趣信息

    Clay Bridges在他的回答中提供了几个使用C预处理器的示例。关于Order语言的一个例子很有趣。Order的作者确实提出了他/她遇到的一个问题,即C预处理器实现可能无法完全实现最新的标准

    一般来说,使用C预处理器来开发某种Bastic语言,如Steve Bourne在为UNIX编写Burne shell时所做的是一个活动,我会考虑适当的理由来进行多次水上会话。

    关于C预处理器,需要记住的主要一点是它正在处理文本标记。因此,C预处理器将允许对语法进行相当多的修补。例如,下面的宏(使用VisualStudio2005编译时没有错误)显示了可能的非直观文本操作

    #define TESTOP(a,x,y,op,z)  a (x) op (y); z
    
    void f(void)
    {
        int i = 0, j = 5;
    
        TESTOP( ,i,j,+=, );
        TESTOP( ,i,(j + 2),+=, );
        TESTOP({,i,(j + 2),+=,});
    }
    
    但是,在推进边界时,您确实需要理解并绕过C预处理器的一些限制。请参阅一些要考虑的问题。

    您可以将C预处理器用作通用的宏和文本预处理器,以C编译器以外的其他工具为目标。例如,老版本使用C预处理器来提供广泛的宏功能

    我看到C预处理器最有效的应用是简化复杂的代码和声明

    我见过的一个例子是使用C预处理器提供状态machi
    BEGIN_MESSAGE_MAP(CFrameworkWndDoc, CWindowDocument)
        //{{AFX_MSG_MAP(CFrameworkWndDoc)
        ON_WM_CHAR()
        ON_WM_TIMER()
        ON_MESSAGE(WU_EVS_DFLT_LOAD, OnDefaultWinLoad)
        ON_MESSAGE(WU_EVS_POPUP_WINDOW, OnPopupWindowByName)
        ON_MESSAGE(WU_EVS_POPDOWN_WINDOW, OnPopdownWindowByName)
        ON_MESSAGE(WM_APP_CONNENGINE_MSG_RCVD, OnConnEngineMsgRcvd)
        ON_MESSAGE(WM_APP_XMLMSG_MSG_RCVD, OnXmlMsgRcvd)
        ON_MESSAGE(WM_APP_BIOMETRIC_MSG_RCVD, OnBiometricMsgRcvd)
        ON_MESSAGE(WM_APP_SHUTDOWN_MSG, OnShutdownMsgRcvd)
        ON_MESSAGE(WM_POWERBROADCAST, OnPowerMsgRcvd)
        ON_MESSAGE(WM_APP_SHOW_HIDE_GROUP, OnShowHideGroupMsgRcvd)
        //}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    
        #define BEGIN_MESSAGE_MAP(theClass, baseClass) \
            PTM_WARNING_DISABLE \
            const AFX_MSGMAP* theClass::GetMessageMap() const \
                { return GetThisMessageMap(); } \
            const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap() \
            { \
                typedef theClass ThisClass;                        \
                typedef baseClass TheBaseClass;                    \
                static const AFX_MSGMAP_ENTRY _messageEntries[] =  \
                {
    
        #define END_MESSAGE_MAP() \
                {0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \
            }; \
                static const AFX_MSGMAP messageMap = \
                { &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; \
                return &messageMap; \
            }                                 \
            PTM_WARNING_RESTORE
    
    // for Windows messages
    #define ON_MESSAGE(message, memberFxn) \
        { message, 0, 0, 0, AfxSig_lwl, \
            (AFX_PMSG)(AFX_PMSGW) \
            (static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM) > \
            (memberFxn)) },
    
    #define ON_WM_TIMER() \
        { WM_TIMER, 0, 0, 0, AfxSig_vw, \
            (AFX_PMSG)(AFX_PMSGW) \
            (static_cast< void (AFX_MSG_CALL CWnd::*)(UINT_PTR) > ( &ThisClass :: OnTimer)) },