2012-12-18 6 views
5

मेरा कोड इस तरह के कंपाइलर आवेषणों का व्यापक उपयोग करता है ताकि रन टाइम पर प्राथमिकता में निर्माण समय पर त्रुटियों को ध्वजांकित किया जा सके और रन टाइम पर आवेदकों को निष्पादित न करके प्रदर्शन में सुधार किया जा सके।सी कंपाइलर आवेषण: अभिव्यक्ति तय होने पर गतिशील रूप से उनका उपयोग कैसे करें?

#define COMPILER_ASSERT(EXPR) switch (0) {case 0: case (EXPR):;} 

सभी अच्छे। मैं निम्नलिखित मामले के लिए कंपाइलर आवेषण का उपयोग करने के लिए इसे विस्तारित करना चाहता हूं। मान लें कि मेरे पास एक मैक्रो है जिसे 100 स्थानों से बुलाया जाता है, जिनमें से 99 एक निश्चित मान पास करते हैं, जिनमें से 1 एक चर को पास करता है। मैं मैक्रो को 99 स्थानों में एक कंपाइलर जोर देने और आखिरी में एक रनटाइम जोर देने के लिए कैसे कोड कर सकता हूं।

यदि मैं गारंटी दे सकता हूं कि MY_FUNCTION() को हमेशा एक निश्चित मान के साथ बुलाया गया था, तो मैं इसे इस तरह कोड कर सकता था।

void my_function(int x) 
{ 
    //do something 
} 

#define MY_FUNCTION(X) \ 
    COMPILER_ASSERT(X != 0); \ 
    my_function(X) 

//These can all take advantage of a compiler assert. 
MY_FUNCTION(1); 
MY_FUNCTION(SOME_HASH_DEFINE); 
MY_FUNCTION(sizeof(SOME_STRUCTURE)); 
//This can't (this is a contrived example - actual code is complex). 
int some_variable = 1; 
MY_FUNCTION(some_variable); 

तो, अगर मैं गारंटी नहीं दे सकते कि एक्स तय हो गई है, लेकिन MY_FUNCTION की प्रत्येक कॉल के लाभ लेना चाहते हैं() कहां है, मैं इसे कैसे कोड करते हैं? कुछ ऐसा:

#define MY_FUNCTION(X) \ 
    if (X is a fixed value) COMPILER_ASSERT(X != 0); \ 
    else assert(X != 0); \ 
    my_function(X) 

केवल My_FUNCTION() को कॉल को रिकोड करने के लिए केवल निश्चित मान पास करने के लिए मेरे लिए एक विकल्प नहीं है। हां, मैं MY_FUNCTION_FIXED_X और MY_FUNCTION_VARIABLE_X को परिभाषित कर सकता हूं लेकिन यह सब कॉलिंग कोड पर इसका खुलासा करता है।

आपकी मदद के लिए धन्यवाद। NickB

+1

शायद आप सी 11 का उपयोग कर सकते हैं, जिसमें वास्तविक संकलन-समय का दावा है? –

+0

जब आप तय कहते हैं, तो क्या आपका मतलब समय स्थिरता है? यदि हां, तो मुझे लगता है कि क्लाइंट कोड में 99 कॉल में मूल्य अलग होगा, क्या यह सही है? – Anon

+0

सही। एक उदाहरण यह है कि MY_FUNCTION (X) को दिया गया मान पूर्णांक की एक विशिष्ट सीमा में होना चाहिए, और मैं यह कहना चाहता हूं कि एक्स सीमा में है। – NickB

उत्तर

2

अपने सी संकलक चर लंबाई सरणियों का समर्थन करता है, तो आप की तरह कुछ लिख सकते हैं:

(assert((EXPR)), (void) sizeof(char[-1])) 
:

#define GENERIC_ASSERT(EXPR) \ 
    ((EXPR) ? (void) 0 : assert((EXPR)), (void) sizeof(char[(EXPR) ? 1 : -1])) 

तो EXPR एक झूठी-मान संकलन समय स्थिर है, यह करने के लिए कम कर देता है

जो संकलित त्रुटि है (इसमें ऋणात्मक-लंबाई सरणी शामिल है)।

तो EXPR एक सच्चे-मान संकलन समय स्थिर है, हम पाते हैं:

((void) 0), (void) 1) 

बजना और जीसीसी दोनों कुछ भी नहीं करने के लिए ज़ोर कम करने अगर एक सच्चे-मान संकलन समय निरंतर साथ लागू करने में सक्षम हैं।

तो EXPR एक क्रम महत्व है, sizeof अभिव्यक्ति यदि लागू एक रनटाइम त्रुटि में परिणाम होगा (जैसे एक बीच में बंद करें), इसलिए assert अल्पविराम ऑपरेटर के उपयोग के माध्यम से पहली अनुक्रम है।

संकलन समय निरंतर मामले में

दुर्भाग्य से, जीसीसी द्वारा त्रुटि संदेश उत्पादन विशेष रूप से रोशन नहीं कर रहा है:

error: array size is negative 
    GENERIC_ASSERT(2 + 2 == 5); 
    ^~~~~~~~~~~~~~~~~~~~~~~~~~ 
note: expanded from: 
    ((EXPR) ? (void) 0 : assert((EXPR)), (void) sizeof(char[(EXPR) ? 1 : -1])) 
                  ^~~~~~~~~~~~~~~ 
+0

मुझे नहीं लगता कि यह वही था जो मैं बाद में था। मैं कुछ ऐसा ढूंढ रहा हूं जो अभिव्यक्ति को स्थिर करता है और अभिव्यक्ति परिवर्तनीय होने पर केवल एक रनटाइम पर संकलन करता है, इसलिए निष्पादन योग्य कोड से निष्पादित करके सर्वश्रेष्ठ रनटाइम प्रदर्शन देना किसी भी आवेषण जिसका परिणाम संकलन में जाना जाता है पहर। – NickB

+0

@NickB यदि 'EXPR' एक संकलित समय स्थिर है, तो 'जोर' एक गैर-पहुंच योग्य शाखा में है (चूंकि' EXPR' सत्य है, इसलिए '(शून्य) 0' शाखा ली जाती है) इसलिए उपर्युक्त संकलित हो जाएगा एक खाली बयान – ecatmur

0

कैसे इस बारे में:

prog.c:5: error: size of array ‘type name’ is negative 

बजना में यह थोड़ा बेहतर है

#define MY_FUNCTION(X) \ 
    do{ \ 
if (X>=1 && X<=20) {\ 
COMPILER_ASSERT(X != 0); \ 
my_function(X);\ 
}\ // end if block 
    // you can use break here too 
    else myfunction2(X,__FILE__,__LINE__); \ // this will be the runtime assert 
}while (0); 


void myfunction2(int x, const char * file, const int line) 
{ 
// print here information 
exit(-1); 
} 
0

पी 99 में मेरे पास स्थैतिक आवेषण के लिए यह मैक्रो है

# if p99_has_feature(c_static_assert) 
# define static_assert _Static_assert 
# else 
# define static_assert(EXPR, DIAGSTR)       \ 
extern char const p00_compiletime_assert[       \ 
sizeof((void const*[3*(!!(EXPR)) - 1]){       \ 
    &p00_compiletime_assert,          \ 
    "static assertion failed: " P99_STRINGIFY(EXPR) ", " DIAGSTR}) \ 
] 
extern char const p00_compiletime_assert[sizeof(void const*[2])]; 
# endif 
#endif 

इसका लाभ यह है कि आप लगभग हर जगह इसका उपयोग कर सकते हैं, कम से कम सी 99 के साथ, जहां एक घोषणा का उपयोग किया जा सकता है। (सी 99 कथन और घोषणाओं को मिश्रण करने की अनुमति देता है) तो इसका उपयोग किसी भी प्रकार के फ़ंक्शन ब्लॉक के अंदर या फ़ाइल स्कोप में किया जा सकता है बशर्ते EXPR एक संकलित समय पूर्णांक निरंतर है।

संबंधित मुद्दे