7

コードのさまざまな低レベル部分で、特定のバイトをデバイスに送信して、物事を実現する必要があります。そのため、次のようなコードがたくさんあります。

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 の範囲外であるため。

私が考えることができる2つの回避策があります:

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 *)にキャストする必要があります)

これらの文字列を宣言するより良い方法はありますか?

4

3 に答える 3

4

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 );

.data()または、C 関数に渡すために繰り返し呼び出すのを避けるには:

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?");

プレーンな char 配列と比較してオーバーヘッドはありません。

于 2013-03-29T03:21:15.683 に答える
1

次のようにして、単一のキャストを作成できます。

const unsigned char magic_bytesUC[] = { 0x01, 0xFA, 0x92 };
enum { NBYTES = sizeof(magic_bytesUC) };
const char *magic_bytes = reinterpret_cast<const char*>(magic_bytesUC);
于 2013-03-29T01:46:06.910 に答える
1

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__)) }
于 2013-03-29T02:10:11.583 に答える