如何实现无需预处理器的数值常量十进制字符串长度常量表达式?
获取数值常量十进制字符串长度的常量表达式方案
预处理器实现方案
要获取UINT64_MAX这类数值常量的十进制字符串长度,可以通过预处理器字符串化的方式实现,代码如下:
#define stringify(x) #x constexpr size_t maxlen {std::char_traits<char>::length(stringify(UINT64_MAX))};
这种方式利用预处理器的#运算符将常量转为字符串,再通过std::char_traits<char>::length在编译期计算字符串长度。
无预处理器的常量表达式方案
如果不想依赖预处理器,可以借助std::numeric_limits<T>来实现,但需要注意其成员的具体含义:
测试与问题分析
运行以下测试代码:
#include <iostream> #include <limits> int main() { std::cout << std::numeric_limits<uint64_t>::digits10 << std::endl; std::cout << std::numeric_limits<uint64_t>::max_digits10 << std::endl; }
部分环境下输出:
19 0
这里digits10表示该类型能精确表示的最大十进制位数,对于uint64_t来说是19,但UINT64_MAX的十进制字符串长度是20,所以直接用digits10无法得到正确结果。
而max_digits10在C++11标准中,对于整数类型的定义是:确保将该类型的任意值转换为字符串再转回原类型时不会丢失精度的最小十进制位数。对于无符号整数的最大值,这个值恰好等于其十进制字符串的长度。但部分旧编译器可能未正确实现该成员,导致返回0。
通用解决方案
对于无符号整数类型,std::numeric_limits<T>::digits10 + 1是可靠的常量表达式方案:
digits10的本质是floor(log10(2^N - 1))(N为类型的位宽)- 无符号类型最大值的十进制位数是
floor(log10(2^N - 1)) + 1,也就是digits10 + 1
如果编译器支持C++11及以后的标准,直接使用std::numeric_limits<T>::max_digits10更直观,它会直接返回正确的长度(比如uint64_t对应20)。
内容的提问来源于stack exchange,提问作者claymation
相关产品推荐
相关产品推荐

