2013-03-29 10 views
6

में चार हेक्साडेसिमल स्थिरांक घोषित करना हमारे कोड के विभिन्न निम्न-स्तर वाले हिस्सों में, हमें चीजों को घटित करने के लिए किसी डिवाइस को विशिष्ट बाइट्स भेजने की आवश्यकता होती है। जैसे, हम कोड है कि लग रहा है के बहुत सारे है की तरह:सी ++ 11

const char magic_bytes[] = { 0x01, 0xFA, 0x92 }; 

कौन सा (जीसीसी 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 127.

को रेंज -128 के बाहर है त्रुटि में परिणाम

const char magic_bytes[] = { static_cast<char>(0x01), static_cast<char>(0xFA), static_cast<char>(0x92) }; 

या:

दो तरीके दिए है कि मैं के बारे में सोच सकते हैं

012,351,
const unsigned char magic_bytes[] = { 0x01, 0xFA, 0x92 }; 

दोनों जो या तो बदसूरत (पहला मामला) कर रहे हैं, या अन्य कमियां

वहाँ घोषित करने के लिए एक बेहतर तरीका है (उत्तरार्द्ध के मामले में करने के लिए (स्थिरांक चार *) कास्ट करने के लिए हो रही है) की ये तार?

+4

चूंकि आप तकनीकी रूप से 'हस्ताक्षरित चार' के साथ काम कर रहे हैं, तो आपको 'char' पर क्यों डालना होगा? मैक्रोज़ के साथ रूपांतरण छिपाने से कम, वास्तव में एक neater समाधान नहीं है। – Dave

+2

@ डेव: अफसोस की बात है, सी और सी ++ में "बाइट्स की सरणी" के लिए सार्वभौमिक प्रतीक 'char *' है, न कि 'हस्ताक्षरित char * '। इसलिए यही कारण है कि आपको आमतौर पर कास्ट की आवश्यकता होती है। हां, यह वास्तव में 'शून्य * होना चाहिए, लेकिन कई एपीआई इसके बजाय' char * 'लेते हैं। –

उत्तर

4

सी ++ 11 आप variadic templates (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); 

या बार-बार यह सी funcs को पारित करने के लिए बुला .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?"); 

कोई सादा चार सरणी की तुलना में भूमि के ऊपर है।

1

आप एक एकल कलाकारों के लिए कुछ इस तरह कर सकते हैं:

const unsigned char magic_bytesUC[] = { 0x01, 0xFA, 0x92 }; 
enum { NBYTES = sizeof(magic_bytesUC) }; 
const char *magic_bytes = reinterpret_cast<const char*>(magic_bytesUC); 
1

के बाद से आपके द्वारा निर्दिष्ट सी ++ 11, मैं तुम्हें variadic macros उपयोग कर सकते हैं मान लेंगे। इस मामले में एक समाधान होता है जो उपयोग किए जाने पर सुरुचिपूर्ण होता है, लेकिन बदसूरत के रूप में वे पीछे के दृश्यों के रूप में आते हैं।

तो मैं आपको दिखा कैसे आप इसका उपयोग से शुरू करेंगे:

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__)) } 
+0

क्या वेरिएड मैक्रोज़ सी ++ 03 के साथ संगत पीछे हैं? या, हमें स्वीकार्य, क्या वे पिछले संस्करणों में जीसीसी एक्सटेंशन के रूप में पेश किए गए थे (कहें, जीसीसी 4.2)? – Damien

+1

@ डेमियन: हां (एक जीसीसी विस्तार), यद्यपि यदि आप वापस नाम पर जाते हैं तो नामित पैरामीटर में वाक्यविन्यास बदलता है, 'nameOfArgs ...' के साथ। मेरी परियोजनाओं में मेरे पास वैरैडिक मैक्रोज़ पर स्वैप करने की जांच है (और मैं सामान्य बिट्स में सभी परिवर्तनों को रखने के लिए अंतिम पंक्तियों से टिप्पणी फॉर्म का उपयोग करता हूं), लेकिन इसका स्पष्ट रूप से अधिक कोड है। समस्या यह है कि यह सी 99, और सी ++ 11 तक मानकीकृत नहीं था।मुझे नहीं पता कि जीसीसी में मानकों-अनुरूप फॉर्म कितने समय से हैं, लेकिन मुझे यकीन है कि 4.2 में यह था। उससे पहले शायद पहले के संस्करण। – Dave