在本周大师的this article中,有人说:It is illegal to #define a reserved word.
这是真的吗?我找不到常规,我已经看过程序员重新定义新的,例如。
答案 0 :(得分:19)
17.4.3.1.1宏名[lib.macro.names]
1如果翻译单元包含标题,则在标题中定义为宏的每个名称都保留给实现用于任何用途。 2包含标题的翻译单元不得包含定义在该标题中声明或定义的名称的任何宏。 此类翻译单元也不应为与关键字词汇相同的名称定义宏。
顺便说一下,new
是一个操作符,用户可以通过提供自己的版本来重载(替换)。
答案 1 :(得分:11)
C ++ 11的相应部分:
17.6.4.3.1宏名称[macro.names]
1包含标准库标题的翻译单元不得在任何标准库标题中声明#define或#undef名称。
2翻译单位不得#define或#undef名称与关键字词汇相同。
C ++ 03中的第1段已被删除。第二段分为两部分。现在,上半部分已更改为明确指出它仅适用于标准标头。第二点已扩大到包括任何翻译单元,而不仅仅包括标题。
但是,标准的此部分概述( 17.6.4.1 [constraints.overview] )指出:
本节介绍对使用C ++标准库功能的C ++程序的限制。
因此,如果您没有使用C ++标准库,那么您可以按照自己的意愿行事。
因此,要在C ++ 11的上下文中回答您的问题:如果您使用的是C ++标准库,则无法在任何翻译单元中定义(或取消定义)与关键字相同的任何名称。
答案 2 :(得分:2)
如果你不想让别人使用goto,你可以做一些小事。只需将以下内容放在他的代码中,他就不会注意到它。
#define goto { int x = *(int *)0; } goto
现在每次他尝试使用goto语句时,他的程序都会崩溃。
答案 3 :(得分:2)
他们在那里实际上是错的,或者至少不讲述它的全部故事。它被禁止的真正原因是它违反了单一定义规则(顺便提一下,这也是为什么它是非法的第二个原因)。
要了解它实际上是允许的(重新定义关键字),至少如果不使用标准库,则必须查看标准的完全不同部分,即转换阶段。它表示输入仅在预处理发生之前被分解为预处理器标记,并且在private
和fubar
之间没有区别,它们都是预处理器的identifiers
。稍后当输入被分解为token
时,替换已经发生。
有人指出,使用标准库的程序存在限制,但重新定义private
的例子并不明显(与“人#4:语言”相反)律师“片段,用于输出到cout
)。
在上一个例子中提到过,这个技巧不会被其他翻译单元或其他翻译单元践踏。考虑到这一点,您应该考虑标准库在其他地方使用的可能性,这将使这一限制生效。
答案 4 :(得分:0)
据我所知,这并不是非法的 - 如果你没有编译我会遇到错误
#define true false
#defining
由于其他原因,某些关键字可能会在编译时产生错误。但是其中很多只会导致非常奇怪的程序行为。