在c++ 11中声明字符十六进制常量
Declaring char hexadecimal constants in C++11
在代码的各个低级部分,我们需要向设备发送特定的字节以使事情发生。因此,我们有很多代码看起来像:
const char magic_bytes[] = { 0x01, 0xFA, 0x92 };
这会导致错误(在GCC 4.7.2上)
test_char.cpp:6:51: warning: narrowing conversion of ‘250’ from ‘int’ to ‘const char’ inside { } is ill-formed in C++11 [-Wnarrowing]
因为0xFA在-128到127的范围之外。
我能想到两种解决方法:
const char magic_bytes[] = { static_cast<char>(0x01), static_cast<char>(0xFA), static_cast<char>(0x92) };
或:
const unsigned char magic_bytes[] = { 0x01, 0xFA, 0x92 };
这两种方法要么很难看(第一种情况),要么有其他缺点(在后一种情况下必须强制转换为(const char*))
是否有更好的方式来声明这些字符串?
c++ 11提供了可变模板(GCC支持已经存在一段时间了)来解决这个问题。
template <typename... A>
constexpr std::array<char, sizeof...(A)> byte_array(A... v)
{ return std::array<char, sizeof...(A)>{{static_cast<char>(v)...}}; }
constexpr auto arr = byte_array( 0x01, 0xFA, 0x92 );
或者为了避免在传递给C函数时重复调用.data()
:
template <std::size_t S>
struct byte_array {
char data_[S];
char *data() { return data_; }
operator char*() { return data_; }
const char *data() const { return data_; }
operator const char*() const { return data_; }
constexpr std::size_t size() const { return S; }
// one could add support for begin/end and things like that
};
template <typename... A>
constexpr byte_array<sizeof...(A)> make_byte_array(A... v)
{ return byte_array<sizeof...(A)>{{static_cast<char>(v)...}}; }
// beside constexpr, this can be also non-const
auto magic_bytes = make_byte_array( 0x01, 0xFA, 0x92 );
strtok(magic_bytes, "why?");
与普通字符数组相比没有开销
您可以这样做来实现单类型转换:
const unsigned char magic_bytesUC[] = { 0x01, 0xFA, 0x92 };
enum { NBYTES = sizeof(magic_bytesUC) };
const char *magic_bytes = reinterpret_cast<const char*>(magic_bytesUC);
既然您指定了c++ 11,那么我假定您可以使用可变宏。在这种情况下,有一种解决方案在使用时很优雅,但在幕后却很难看。
那么我将从如何使用它开始:
char myBytes1[] = MAKE_BYTES( 0x00, 0x40, 0x80, 0xC0 );
char myBytes2[] = MAKE_BYTES( 0xFF );
现在,后端代码:这可以更短,但我使用了标准的循环方法,因此您可以从中获得一些重用。它可以支持1 - 24字节的列表。通过重复最后几行,它可以变得更大。欢迎来到预处理器元编程的世界。
#define EXPAND(a) a
#define ARGS_COUNT_(
_96,_95,_94,_93,_92,_91,_90,_89,_88,_87,_86,_85,_84,_83,_82,_81,
_80,_79,_78,_77,_76,_75,_74,_73,_72,_71,_70,_69,_68,_67,_66,_65,
_64,_63,_62,_61,_60,_59,_58,_57,_56,_55,_54,_53,_52,_51,_50,_49,
_48,_47,_46,_45,_44,_43,_42,_41,_40,_39,_38,_37,_36,_35,_34,_33,
_32,_31,_30,_29,_28,_27,_26,_25,_24,_23,_22,_21,_20,_19,_18,_17,
_16,_15,_14,_13,_12,_11,_10, _9, _8, _7, _6, _5, _4, _3, _2, _1,
N,...) N
#define ARGS_COUNT(...) ARGS_COUNT_(__VA_ARGS__,
96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,
80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,
64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,
48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,
32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,
16,15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define ARGS_HEAD(a,...) (a)
#define ARGS_TAIL(a,...) (__VA_ARGS__)
#define FOREACH(macro,lmacro,list) FOREACH_(ARGS_COUNT list,macro,lmacro,list)
#define FOREACH_(n,macro,lmacro,list) FOREACH__(n,macro,lmacro,list)
#define FOREACH__(n,macro,lmacro,list) FOREACH_##n(macro,lmacro,list)
#define FOREACH_1(macro,lmacro,list) lmacro list
#define FOREACH_2(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_1(macro,lmacro,ARGS_TAIL list)
#define FOREACH_3(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_2(macro,lmacro,ARGS_TAIL list)
#define FOREACH_4(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_3(macro,lmacro,ARGS_TAIL list)
#define FOREACH_5(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_4(macro,lmacro,ARGS_TAIL list)
#define FOREACH_6(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_5(macro,lmacro,ARGS_TAIL list)
#define FOREACH_7(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_6(macro,lmacro,ARGS_TAIL list)
#define FOREACH_8(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_7(macro,lmacro,ARGS_TAIL list)
#define FOREACH_9(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_8(macro,lmacro,ARGS_TAIL list)
#define FOREACH_10(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_9(macro,lmacro,ARGS_TAIL list)
#define FOREACH_11(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_10(macro,lmacro,ARGS_TAIL list)
#define FOREACH_12(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_11(macro,lmacro,ARGS_TAIL list)
#define FOREACH_13(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_12(macro,lmacro,ARGS_TAIL list)
#define FOREACH_14(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_13(macro,lmacro,ARGS_TAIL list)
#define FOREACH_15(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_14(macro,lmacro,ARGS_TAIL list)
#define FOREACH_16(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_15(macro,lmacro,ARGS_TAIL list)
#define FOREACH_17(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_16(macro,lmacro,ARGS_TAIL list)
#define FOREACH_18(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_17(macro,lmacro,ARGS_TAIL list)
#define FOREACH_19(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_18(macro,lmacro,ARGS_TAIL list)
#define FOREACH_20(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_19(macro,lmacro,ARGS_TAIL list)
#define FOREACH_21(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_20(macro,lmacro,ARGS_TAIL list)
#define FOREACH_22(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_21(macro,lmacro,ARGS_TAIL list)
#define FOREACH_23(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_22(macro,lmacro,ARGS_TAIL list)
#define FOREACH_24(macro,lmacro,list) EXPAND(macro ARGS_HEAD list) FOREACH_23(macro,lmacro,ARGS_TAIL list)
#define MAKE_BYTE(x) static_cast<char>(x),
#define MAKE_LAST_BYTE(x) static_cast<char>(x)
//#define MAKE_BYTES(x) { FOREACH(MAKE_BYTE,MAKE_LAST_BYTE,x) } // uncomment this if you would rather use double bracket ((0x00,0x40,...)) syntax
#define MAKE_BYTES(...) { FOREACH(MAKE_BYTE,MAKE_LAST_BYTE,(__VA_ARGS__)) }
相关文章:
- 将字符指针十六进制转换为字符串并保存在文本文件C++中
- 如何将一个ostringstream十六进制字符串字符对转换为单个unit8t等价的二进制值
- 在 std::无符号字符的向量处存储 int 的十六进制表示形式
- 打印十六进制字符
- 将十六进制值设置为用于填充的字符变量时出现问题
- 如何将带有十六进制值的 std::string 转换为 std::vector<无符号字符>
- 在 c++ 中以十六进制格式打印无符号字符(BYTE).使用 std::cout
- 在Arduino中将字符串转换为(逗号分隔的十六进制)字符串到无符号字符数组
- 用无符号字符制作十六进制
- 如何从 QString 中包含的十六进制值中获取 ASCII 字符?
- 字符数组到十六进制字符串的转换 - 意外输出
- 使用C++将越南语字符从ISO88591、UTF8、UTF16BE、UTF16LE和UTF16编码为十六进制,反之亦然
- C++十六进制字符串转换为十六进制的字符 *
- 将字符指针中的十六进制转换为十进制
- 十六进制 QString 表示为无符号字符数组
- 从十六进制字符串转换为十六进制字符数组
- 字符数组中的十六进制导致写入套接字时出现随机字符
- 将十六进制字符数组存储在字节数组中,而无需更改为 ASCII 或其他任何东西
- 在c++ 11中声明字符十六进制常量
- 转换字符>十六进制