为什么此代码无效
std::string strVariant = "8000";
short i16Value = 0;
std::string::iterator it = strVariant.begin();
if (qi::parse(it, strVariant.end(), qi::int_parser<short, 16>(), i16Value))
{
int a = 5;
}
我希望值-32768。但解析失败,i16Value包含0x800。 我使用boost 1.56.00
答案 0 :(得分:2)
这是在Spirit内部的溢出检查失败。要解决此问题,请使用uint_parser
将signed short作为模板参数传递:
qi::uint_parser<short, 16>()
更新:从源代码中提取 提升1.60
spirit \ home \ qi \ numeric \ detail \ numeric_utils.hpp +142
inline static bool add(T& n, Char ch, mpl::true_) // checked add
{
// Ensure n *= Radix will not overflow
typedef constexpr_int<T, boost::integer_traits<T>::const_max> max;
typedef constexpr_int<T, max::value / Radix> val;
if (n > val::value)
return false;
现在:
val::value = 32767/16 = 2047
n = 2048 (0x800) // 3 chars parsed
答案 1 :(得分:1)
这是设计的。
与C ++文字一样,使用iostream或POSIX函数,根据定义,十六进制数字是无符号的。
如果需要,您必须简单地解析为无符号并转换为带符号的类型。
实际上,您可以通过将uint
属性传递给简单的hex
或uint_parser<uint32_t, 16>
来隐式转换它。
为了帮助处理属性强制规则,您可以通过指定“冲突”类型uint_parser<int32_t, 16>
来让转换发生在int解析器本身。
当嵌入你的语法定义时,所有这些都非常微妙,所以我一定要添加一个简单的注释,如果只是为了防止人们“修复”这个bug:)