您能设计一个简单的宏来在使用时有效地产生编译器错误吗?
我正在故意寻找一个奇怪的宏定义:我需要一个以这种方式定义的宏,如果该宏在编译代码中有效使用,编译器将毫无疑问地产生错误。
背景:由于C11引入了几个新的关键字,并且新的C++11标准也添加了一些,所以我想在我的项目中引入一个头文件(主要使用C89/C95编译器,并添加一些内容)来强制开发人员避免使用这些新关键字作为标识符名称,当然,除非它们以预期的方式被识别为关键字。
在古代,我为 new
做了这样的事情:
#define new *** /* C++ keyword, do not use */
是的,它有效。直到它没有发生,当程序员忘记参数名称中的下划线时:
void myfunction(uint16_t new parameter);
从那以后我使用了变体,但我再也没有受到过挑战。
现在我打算创建一个包含各种编译器不支持的所有关键字的文件,并且我正在寻找一个可靠的解决方案,最好有一个不太令人困惑的错误消息。 “语法错误”没问题,但“参数缺失”已经很令人困惑了。
#define atomic +*=*+ /* C11 derived keyword; do not use */
除了我通常的犹豫之外,我正在思考,我很确定任何用途(但不是定义)宏的执行会产生错误。
编辑:为了使它变得更加困难,MISRA 将只允许使用基本源和执行字符集,因此不允许 @
或 $
。
但我想问一下社区:你们有更好的宏观价值吗?同样有效,但更短?或者甚至更长但在某些奇怪的情况下更可靠?或者当“不鼓励”标识符用于任何目的时生成错误的完全不同的方法(请仅使用编译器,而不是外部工具!)?
免责声明: 而且,是的,我知道我可以使用 grep 或解析器在夜间构建上运行,并报告它发现的警告。但是,将立即错误放到开发人员桌面上会更快,并且肯定会在签入之前修复。
I am looking for a strange macro definition, on purpose: I need a macro defined in such a way, that in the event the macro is effectively used in compiled code, the compiler will unfailingly produce an error.
The background: Since C11 had introduced several new keywords, and a new C++11 standard also added a few, I would like to introduce a header file in my projects (mostly using C89/C95 compilers with a few additions) to force developers to refrain from using these new keywords as identifier names, unless, of course, they are recognized as keywords in the intended fashion.
In the ancient past, I did this for new
like this:
#define new *** /* C++ keyword, do not use */
And yes, it worked. Until it didn't, when a programmer forgot the underscore in a parameter name:
void myfunction(uint16_t new parameter);
I used variants since, but I've never been challenged again.
Now I intend to create a file with all keywords not supported by various compilers, and I'm looking for a dependable solution, at best with a not too confusing error message. "Syntax error" would be OK, but "parameter missing" would be confusing already.
I'm thinking along the lines of
#define atomic +*=*+ /* C11 derived keyword; do not use */
and aside from my usual hesitation, I'm quite sure that any use (but not the definition) of the macro will produce an error.
EDIT: To make it even more difficult, MISRA will only allow the use of the basic source and execution character set, so @
or $
are not allowed.
But I'd like to ask the community: Do you have a better macro value? As effective, but shorter? Or even longer but more dependable in some strange situation? Or a completely different method to generate an error (only using the compiler, please, not external tools!) when a "discouraged" identifier is used for any purpose?
Disclaimer:
And, yes, I know I can use a grep or a parser to run on a nightly build, and report the warnings it finds. But dropping an immediate error on the developers desk is quicker, and certain to be fixed before checking in.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如果运动是为了总是产生错误的最短标记序列,则两个不能合法同时出现的 1 字符运算符的任意组合,但
({
或})< /code> 因为 gcc 有特殊含义,所以
<
或> ;
因为它们可以匹配C++ 的模板参数这留下了一些可能性
..
、.|
以及其他与 < 的组合code>. 因为.
需要以下标识符&|
、&/
、&^, <代码>&,,
&;
!|
,!/
,!^
,!,
,!;
但实际上为了更加用户友好,我还首先在其中放置了
_Pragma
,这样编译器也会发出警告。If the sport is for the shortest tokensequence that always produces an error, any combination of two 1 character operators that can't legally occur together, but
({
or})
because gcc has a special meaning for that<
or>
because they could match template parameters for C++This leave some possibilities
..
,.|
and other combinations with.
since.
expects a following identifier&|
,&/
,&^
,&,
,&;
!|
,!/
,!^
,!,
,!;
But actually to be more user friendly I'd also first place a
_Pragma
in it so the compiler would also spit a warning.我认为你可以只使用一个非法符号:
另一个可行的符号是这样的:
它会错误地告诉你你正在改变一个常量。另外,错误消息通常会非常好:
最后一个可能是最短且始终有效的消息是这样的:
因为预处理器永远不会替换两次,并且
#
在预处理器之外是非法的这总是会出错。I think you can just use an illegal symbol:
Another one that would work would be this:
It would error you that you are changing a constant. Also, the error message will usually be quite good:
And the final one that is perhaps the shortest and will always work is this:
Because the preprocessor will never replace twice, and
#
is illegal outside of the prepocessor this will always error.扩展不是递归的,因此它会停止。阻止它成为编译错误的唯一方法是:
但这是禁止的,因为
do
和not
是关键字。错误消息甚至可能包括“原子”。您可以通过重新措辞消息来增加出现这种情况的可能性:(
不过,现在您没有使用消息中的关键字。)
The expansion is not recursive so it stops. The only way to stop it from being a compilation error is:
but that's verboten because
do
andnot
are keywords.The error message might even include 'atomic'. You can increase the probability of that by rephrasing the message:
(Now you are not playing with keywords in the message, though.)
我认为
[[]]
在任何地方都不是有效的标记序列,因此您可以使用它:错误将是语法错误,抱怨
[
或]
。I think
[[]]
isn't a valid sequence of tokens anywhere, so you could use that:The error will be a syntax error, complaining about
[
or]
.我的尝试:
My attempt: