具有尾随注释的多行预处理器宏

时间:2016-06-07 16:11:12

标签: c++ c gcc g++ c-preprocessor

我想定义以下普通的宏:

#define MY_ENUM enum MyEnum{ \
    myVal0, \ //Describes this situation
    myVal2  \ //Describes that situation
}

令我惊讶的是,由于error: stray ‘\’ in program,这不起作用。反斜杠后面甚至有一些空格会产生warning: backslash and newline separated by space。正如this answer指出的那样,反斜杠必须是该行的最后一个字符。 This answer指出在处理注释之前发生了行拼接。之所以选择这个订单,对我来说绝对没有意义;我可以想象这样做的唯一原因是允许多行注释,如下所示:

//This is a comment which \
follows in the next line

这看起来非常危险,因为这样的事情可能会在尝试时吃掉下一行的代码。相反的顺序,即在拼接线之前用单个空格替换每个注释听起来像是一个更明智的选择。有人可以解释为什么做出这个选择吗?

我可以解决以下问题:

#define MY_ENUM enum MyEnum{ \
    myVal1, /*Describes this situation*/ \
    myVal2  /*Describes that situation*/ \
}

我做这个笨拙的枚举宏定义时的目的是这个宏必须在c ++(由于Qt绝对必须是一个类成员)和c之间共享。定义像这样的宏看起来像是我唯一的解决方案,但上面的解决方法看起来很难看,我绝对不想让枚举没有注释。我接近这个问题了吗?

2 个答案:

答案 0 :(得分:2)

问题是,当package testmongo; import com.mongodb.MongoClient; import com.mongodb.MongoClientURI; import com.mongodb.client.MongoDatabase; import com.mongodb.client.MongoIterable; import java.util.LinkedList; import java.util.List; public class MongoConnector { private final MongoClient mongoClient; private MongoDatabase db; public MongoConnector(String host, int port) { this.mongoClient = new MongoClient(host, port); } public MongoConnector(String host, int port, String username, String password) { String textUri = "mongodb://"+username+":"+password+"@"+host+":"+port; MongoClientURI uri = new MongoClientURI(textUri); this.mongoClient = new MongoClient(uri); } public boolean connectToDB(String dbName) { this.db = mongoClient.getDatabase(dbName); return this.db != null; } public List<String> listAllDB() { List<String> ret = new LinkedList<>(); MongoIterable<String> x = mongoClient.listDatabaseNames(); for(String t : x) { ret.add(t.toString()); } return ret; } } 被命中并继续时,c预处理器只会添加另一个行结束符。

\条评论中,您无法做到这一点。不接受//字符来继续评论(它应该显示为单行)。

解决方案是, - 正如您自己发现的那样 - 使用\评论样式。

答案 1 :(得分:1)

要理解这种现象,您可以参考C标准(我相信C ++以这种方式类似于C)。特别是它在翻译阶段部分(C11草案§5.1.1.2)。

预处理器的行为就像按照自上而下的顺序执行阶段一样(即步骤3在完成第2步之后执行等)。

基本上,///* ... */条评论在第三阶段被识别,即在跟踪\处理(即第二阶段)之后执行,意思是这是不可知的。换句话说,它就像普通的源文本一样对待它们,没有特殊意义。

  
      
  1. 删除反斜杠字符(\)后面紧跟一个新行字符的每个实例,将物理源代码行拼接到   形成逻辑源代码行。任何物理上只有最后一个反斜杠   源线应有资格成为此类拼接的一部分。

  2.   
  3. 源文件被分解为预处理标记 7)和空白字符序列(包括注释)。源文件不应以部分预处理标记或部分注释结束。每个注释都由一个空格字符替换。保留换行符。是否每个非空白序列的空白   除了换行之外的其他字符将被保留或替换为一个空格   字符是实现定义的。

  4.