我有这段代码(实际上是垃圾收集的Forth系统的解释器的一部分):
#define PRIMITIVE(name) do { VocabEntry* entry = (VocabEntry*)gc_alloc(sizeof(VocabEntry)); entry->code = name; entry->name = cstr_to_pstr(#name); entry->prev = latest_vocab_entry; latest_vocab_entry = entry; } while (false) PRIMITIVE(dup); PRIMITIVE(drop); PRIMITIVE(swap); // and a lot more
但是有一个问题:在线
entry->name = cstr_to_pstr(#name);
name
字段替换dup
, drop
, swap
和其余部分。 我希望字段名称不被替换。
那么,有没有办法解决这个问题,除了简单地重命名宏参数?
作为答案,请解释一般是否有一种方法来抑制宏体中宏参数名称的替换。 不要回答“只是这样做”(请)。
您可以定义一个不同的宏来扩展name
,如下所示:
#define Name name
并更改PRIMITIVE
宏中的name
字段以使用新的宏,如下所示:
#define PRIMITIVE(name) do { VocabEntry* entry = (VocabEntry*)gc_alloc(sizeof(VocabEntry)); entry->code = name; entry->Name = cstr_to_pstr(#name); entry->prev = latest_vocab_entry; latest_vocab_entry = entry; } while (false)
除了使用与宏体中的参数名称不同的内容或更改参数名称之外,没有其他方法可以在C语言中执行此操作。 Per C 2011(N1570)6.10.3.1 1,当识别出类似函数的宏时,参数名称立即被替换,除非存在#
或##
,并且没有其他例外:
在确定了调用类函数宏的参数之后,发生了参数替换。 替换列表中的参数,除非前面带有#或##预处理标记或后跟##预处理标记(见下文),否则在扩展其中包含的所有宏之后,相应的参数将替换该参数。
#
令牌将参数名称更改为字符串,在这种情况下没有用。 ##
标记扩展参数名称并将其与相邻标记粘贴在一起,在这种情况下也没用。
不,那里没有。
要了解原因,您需要考虑宏扩展实际发生的方式。 扩展类似函数的宏需要三个主要步骤:
标准6.10.3节(C11和C99)对此进行了概述。
这样做的结果是,不可能编写某种可以name
的宏并滥用’##’的抑制规则或类似的东西,因为PRIMITIVE
主体中的替换步骤必须在任何之前完全运行。允许轮到他们识别身体内的宏。 您无法在替换列表中标记令牌以进行抑制,因为只有在替换步骤已经运行后才能检查您可以放置的标记。 由于订单是在标准中指定的,因此您发现的任何可以让您以这种方式标记令牌的漏洞都是编译器错误。
最好我可以建议,如果你真的没有重命名宏参数是将na
和me
作为单独的参数传递给连接宏; 只有在替换完成后才会形成令牌name
并且不再检查列表中的参数名称。
编辑希望我输入更快。
不,没有办法在一个令牌的宏体内抑制与所述宏的声明参数相同的替换。 跳入预处理器代码的每个可能的解决方案都需要您重命名某些内容,可以是参数名称或字段名称(可能只是为了宏的目的,正如Eric的回答所做的那样)。
以上就是c/c++开发分享抑制C宏变量替换相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/545823.html