C++ C预处理器作为语言创建工具的长度/限制是什么?我在哪里可以了解更多关于这些的信息?
比亚恩·斯特劳斯特鲁普在他的报告中说: < p>构建cFAc++,第一个C++ 我第一次用C写了一个 “带类的C”-到C预处理器。“C “带类”是一种C方言 成为C++的直接祖先… 然后我写了第一个版本的 “C与类”中的C前面 当我读到这篇文章时,它激起了我对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原创作品的来源是否随处可见
请注意,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)) },