Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
字符串化块中的空字符文字 简化C++中SQL查询的编写,使用宏< /P> #define SQL(...) #__VA_ARGS___C++_Clang_Language Lawyer_C Preprocessor_C++03 - Fatal编程技术网

字符串化块中的空字符文字 简化C++中SQL查询的编写,使用宏< /P> #define SQL(...) #__VA_ARGS__

字符串化块中的空字符文字 简化C++中SQL查询的编写,使用宏< /P> #define SQL(...) #__VA_ARGS__,c++,clang,language-lawyer,c-preprocessor,c++03,C++,Clang,Language Lawyer,C Preprocessor,C++03,它工作得很好,除非出现空字符串文字(如 SQL(select * from foo where bar = '') ),铿锵(没有其他编译器)发出警告 warning: empty character constant [-Winvalid-pp-token] 我正在做的是一个严重的攻击(我保留它是因为它允许多行sql语句可读),它违反了标准还是在这里过于关键(字符文本没有出现在预处理器指令中) Edit:忘了提到并非所有平台都支持C++11,因此我们不能使用原始字符串文本。我们可能会使用V

它工作得很好,除非出现空字符串文字(如

SQL(select * from foo where bar = '')
),铿锵(没有其他编译器)发出警告

warning: empty character constant [-Winvalid-pp-token]
我正在做的是一个严重的攻击(我保留它是因为它允许多行sql语句可读),它违反了标准还是在这里过于关键(字符文本没有出现在预处理器指令中)


Edit:忘了提到并非所有平台都支持C++11,因此我们不能使用原始字符串文本。我们可能会使用VisualC++9.0几年,而使用GCC4.6-somesnapshot的时间可能会更少,但仍然需要几年。这种攻击也早于C++11。

您所做的是一种严重的攻击,如果您使用Clang(和其他现代编译器)进行编译,但不需要支持较旧的编译器,那么有一种更简单的方法:原始字符串文本

std::string query = R"sql(
  select * from foo where bar = ''
)sql";
这甚至允许您在查询中嵌入引号和反斜杠,而无需转义

作为参考,自Clang3.0、GCC4.5和VisualStudio2013以来,原始字符串文本一直受到支持

从语言律师的角度来看,Clang在允许您的代码编译方面非常慷慨。这是无效的。C++14 2.2说,在第3阶段(宏替换发生在第4阶段),源文件被分解为预处理标记和空格序列

2.5列出了预处理令牌语法生成。这里只有一个选项以单引号开始,即字符文字。字符文字在2.14.3中定义为

character-literal:
    ' c-char-sequence '
    <prefixed versions>

c-char-sequence:
    c-char
    c-char-sequence c-char

c-char:
    any member of the source character set except
        the single-quote ' , backslash \, or new-line character
    escape-sequence
    universal-character-name
字符文字:
“c-字符序列”
c-字符序列:
碳炭
c-char序列c-char
c字符:
源字符集的任何成员,但
单引号、反斜杠或换行符
逃逸序列
通用字符名
请注意,c-char序列至少包含一个c-char,并且c-char不能是单个引号。因此,C++中没有语法生成匹配<代码> '/COD>。在一致性程序中,该序列不能出现在更大的程序之外(如字符串文本)


宏进程在字符级别上不起作用,毕竟它在令牌级别上起作用。一切都需要首先标记化。

这是一个严重的问题:o)我经常做的是:
std::ostringstream sql;sql@Galik:不要在sql中提到字符串操作。那应该是开玩笑!我所说的黑客只是用合适的多行结构来替换双引号,因为我们的SQL语句通常有30行以上的行,如果为了可读性而适当地拆分和缩进的话。如果您拆分字符串文本,就很容易得到可读的多行SQL语句,即。
“select*”(来自foo)“where bar=”
可以拆分为3行(并缩进),但仍然只算作一个字符串文字。@Sanderedycker:是的。除了,好吧,假设您有超过30行的语句,您需要更改它,包括删除、添加、连接和拆分行。添加和删除所有引号都是痛苦的,更不用说您不再获得自动缩进和括号匹配的结果了om大多数编辑器。@Angew:因为尝试确保插入的参数不包含任何特殊字符或正确引用容易出错,如果参数来自用户,错误会导致SQL注入漏洞,否则很难诊断错误。所有数据库都支持参数绑定,以确保正确引用,另外,通常这种语句只解析一次,并且可以使用多个参数替换运行,从而大大节省时间,因为查询不需要重新解析,特别是重新优化。谢谢。我忘了提到它必须编译到Visual Studio 2008和Gcc 4.5.0。哦,问题被标记为language-lawyer。添加了律师的工作。