在本文中,Guru of the week指出:“#define保留字是非法的。”这是真的吗?我没有在规范文件中找到任何信息,并且我已经看到程序员重新定义了“new”等保留字。
17.4.3.1.1 宏名称 [lib.macro.names]
1 在头文件中定义的每个宏名称都保留给实现用于任何用途,如果翻译单元包括该头文件,则如此。164)
2 包含头文件的翻译单元不得包含定义在该头文件中声明或定义的任何名称的宏。也不应将这样的翻译单元定义为与关键字词法上相同的名称的宏。
顺便说一下,new
是一个操作符,用户可以通过提供自己的版本来重新定义(重载)它。
#define new
吗?@JamesKanze:为什么要标准头文件? - qdii对应的C++11章节:
17.6.4.3.1 宏名称 [macro.names]
1 包含标准库头文件的翻译单元不得#define或#undef任何标准库头文件中声明的名称。
2 翻译单元不得#define或#undef与关键字在词法上完全相同的名称。
C++03的第一段已被删除。第二段已分为两个部分。第一半现在已经更改为明确说明它仅适用于标准头文件。第二点已经扩大到包括任何翻译单元,而不仅仅是那些包括头文件的翻译单元。
然而,此章节的概述(17.6.4.1 [constraints.overview])指出:
本节描述使用C++标准库功能的C++程序的限制。
因此,如果您没有使用C++标准库,那么您可以随心所欲。
因此,在C++11的背景下回答您的问题:如果您使用C++标准库,您不能在任何翻译单元中定义(或取消定义)与关键字完全相同的名称。
private
和fubar
之间没有区别,它们都是预处理器的identifiers
。稍后,当输入被分解成token
时,替换已经发生。private
的示例是否在使用它(而不是“Person #4:The Language Lawyer”片段将其用于输出到cout
)。如果你不想让别人使用goto语句,这里有一个小技巧。只需将以下代码放在他的代码中他不会注意到的地方。
#define goto { int x = *(int *)0; } goto
现在每次他尝试使用goto语句,程序就会崩溃。
goto
是不好的,那么你应该不适合写程序。如果你能说服我永远不应该使用goto
,我会非常惊讶。 - Iharob Al Asimigoto
的潜在好用之处。 - chbaker0goto
并不一定是实现有限状态机的最佳方式;在循环中使用switch语句可以使当前状态更加明确。有关何时适用goto
的更多讨论,请参见此答案。 - Keith Thompson据我所知,这并不违法——到目前为止,我所遇到的编译器都不会因为你这样做而生成错误。
#define true false
#定义
某些关键字可能会因其他原因在编译时生成错误。但其中很多只会导致非常奇怪的程序行为。
#define
来改变保留字的含义。事实上,在国际混淆C代码大赛(The International Obfuscated C Code Contest)的参赛作品中经常被使用。这是可能的,因为由#define
定义的宏在实际的C编译器运行之前会被一个单独的程序替换掉。 - Some programmer dude#define new newMac
,在PC上#define new newPc
。在其他翻译单元中,相应的函数将定义特定于平台的内存分配器。我想这个想法是为了在无法重命名每个对new的调用时,在任何地方继续使用new同时具有特定于平台的行为。 - qdii#define for if (false) else for
来修复 Visual Studio 6 在for
循环中声明变量的错误作用域。 - Jack Aidley#define
的此类示例?还是你指的是重载new
运算符?这两件事情完全不同。 - Code-Apprentice#define new newPS3
。游戏行业有点像动物园。 - qdii