2015-01-22 13 views
5

मैं निम्नलिखित समस्या के बारे में सोच रहा हूं: मैं एक प्रोग्राम के साथ एक माइक्रोक्रोनरोलर (चलिए एक एवीआर मेगा प्रकार) कहना चाहता हूं जो कुछ प्रकार की लुक-अप टेबल का उपयोग करता है।संकलन समय पर जीसीसी मूल्यांकन कार्यों को कैसे बनाया जाए?

पहला प्रयास तालिका को एक अलग फ़ाइल में ढूंढना और इसे किसी अन्य स्क्रिप्टिंग भाषा/प्रोग्राम/का उपयोग करके बनाना होगा .... इस मामले में सी

के लिए आवश्यक स्रोत फ़ाइलों को बनाने में काफी प्रयास किए गए हैं।

मेरा विचार अब चीजों को संभालने के लिए प्रीप्रोसेसर और कंपाइलर का उपयोग करना था। मैं साइन मानों की तालिका (सिर्फ एक उदाहरण के रूप में) के साथ इस को लागू करने की कोशिश की:

#include <avr/io.h> 
#include <math.h> 

#define S1(i,n) ((uint8_t) sin(M_PI*(i)/n*255)) 
#define S4(i,n) S1(i,n), S1(i+1,n), S1(i+2,n), S1(i+3,n) 

uint8_t lut[] = {S4(0,4)}; 

void main() 
{ 
    uint8_t val, i; 

    for(i=0; i<4; i++) 
    { 
     val = lut[i]; 
    } 
} 

अगर मैं इस कोड संकलन मैं sin समारोह के बारे में चेतावनी मिलता है। विधानसभा में आगे .data अनुभाग में कुछ भी नहीं है। अगर मैं तीसरी पंक्ति में sin हटा देता हूं तो मुझे असेंबली में डेटा मिलता है। स्पष्ट रूप से सभी जानकारी संकलन समय पर उपलब्ध हैं।

क्या आप मुझे बता सकते हैं कि मेरे इरादे को हासिल करने का कोई तरीका है: संकलक ऑफ़लाइन जितना संभव हो उतना मूल्यों की गणना करता है? या तालिका प्रविष्टियों की गणना करने के लिए बाहरी स्क्रिप्ट/प्रोग्राम/... का उपयोग करने का सबसे अच्छा तरीका है और इन्हें एक अलग फ़ाइल में जोड़ें जो केवल #include डी होगा?

+1

"काफी कुछ प्रयास" लिखने यह एक बार उत्पन्न करने के लिए और बस में पेस्ट कर सकते हैं -। एक अच्छा पटकथा के साथ भाषा? सी के साथ समस्या पर हमला करने से निश्चित रूप से कम .... –

+0

सी ++ 11 (सी ++ 14 के साथ सुधार) संकलन समय पर एक समारोह निष्पादित करने के लिए कंपाइलर के संकेत के रूप में 'constexpr' है। – johannes

+0

@johannes: 'constexpr' का कोई फायदा नहीं है। यह संकलन समय पर केवल एक अभिव्यक्ति का मूल्यांकन किया जा रहा है (और संकलक को इसके लिए भी मजबूर कर रहा है, उदाहरण के लिए एक गणना को असाइन करके इसे उसी स्रोत फ़ाइल में किसी अन्य स्थान पर रनटाइम पर फिर से मूल्यांकन करने से नहीं रोकता है!)। यह कुछ भी लागू या संकेत नहीं करता है। उस ने कहा, मेरा जीसीसी ओपी में कोड स्निपेट को एक संकलित-मूल्यांकन लुकअप टेबल (बिना किसी विशेष विशेष नृत्य के) में ठीक करता है। – Damon

उत्तर

4

सामान्य समस्या है कि यहाँ sin कॉल सी भाषा के नियमों के अनुसार, इस आरंभीकरण वास्तविक अवैध बनाता है, के रूप में यह नहीं निरंतर अभिव्यक्ति से प्रति है और आप स्थिर भंडारण अवधि, जिसके लिए आवश्यक है की सरणी आरंभ कर रहे हैं उस। यह भी बताता है कि आपकी सरणी .data अनुभाग में क्यों नहीं है।

सी 11 (N1570) §6.6/2,3 लगातार भाव (जोर मेरा)

एक निरंतर अभिव्यक्ति बजाय अनुवाद क्रम, के दौरान मूल्यांकन किया जा सकता है और उसके अनुसार किसी भी स्थान पर इस्तेमाल किया जा सकता है कि एक स्थिर हो सकता है।

लगातार भाव करेगा नहीं शामिल काम, वेतन वृद्धि, घटती, समारोह-फोन, या अल्पविराम ऑपरेटर, जब वे कर रहे एक उपसूचक कि है नहीं evaluated.115)

के भीतर निहित छोड़कर हालांकि @ शाफिक यघमोर की टिप्पणी के अनुसार जीसीसी sin फ़ंक्शन कॉल को इसके अंतर्निर्मित समकक्ष के साथ प्रतिस्थापित करेगा (जब तक -fno-builtin विकल्प मौजूद नहीं है), जिसे निरंतर अभिव्यक्ति के रूप में माना जाने की संभावना है।6.57 Other Built-in Functions Provided by GCC के अनुसार:

जीसीसी शामिल निर्मित मानक सी पुस्तकालय में कार्यों के कई संस्करणों। __builtin_ के साथ उपसर्ग किए गए संस्करण हमेशा को सी लाइब्रेरी फ़ंक्शन के समान अर्थ के रूप में माना जाता है, भले ही आप -fno-builtin विकल्प निर्दिष्ट करते हैं।

+1

यह संभवतः काम करता है क्योंकि वर्तमान में [जीसीसी गणित बिल्टिन का इलाज करता है क्योंकि वे लगातार अभिव्यक्ति थे] (http://stackoverflow.com/q/27744079/1708801), '-fno-builtin' का उपयोग करके समान कोड 'gcc' का उपयोग करके विफल हो जाता है लेकिन यह केवल अन्यथा एक चेतावनी उत्पन्न करता है। –

+0

@ShafikYaghmour: फिर disassembly में कोई डेटा क्यों नहीं है। मैं पूरी तरह से अनिश्चित हूं, अगर मैं डेटा तक पहुंचने का प्रयास करता हूं तो क्या होगा ... –

+0

@ क्रिस्टियनवॉल्फ: आप इसे '__builtin_sin' द्वारा मजबूर कर सकते हैं, लेकिन मैं शाफिक से सहमत हूं, कि यह संभवतः काम करता है। शायद आप कुछ avr-gcc पोर्ट का उपयोग कर रहे हैं, जो इसका समर्थन नहीं करता है? –

2

आप जो कोशिश कर रहे हैं वह सी भाषा का हिस्सा नहीं है। इन परिस्थितियों में, मैं इस पैटर्न निम्नलिखित कोड लिखा है:

#if GENERATE_SOURCECODE 
int main (void) 
{ 
    ... Code that uses printf to write C code to stdout 
} 
#else 
    // Source code generated by the code above 
    ... Here I paste in what the code above generated 

    // The rest of the program 
#endif 

हर बार जब आप इसे बदलने की जरूरत है, तो आप परिभाषित GENERATE_SOURCECODE साथ कोड चलाने के लिए, और उत्पादन में पेस्ट करें। यदि आपका कोड स्वयं निहित है और जेनरेट आउटपुट केवल तब ही बदलता है जब कोड उत्पन्न होता है।

+0

का उपयोग करेंगे, आपके पास सही समाधान की शुरुआत है। – Joshua

+0

यह इस अर्थ में इष्टतम नहीं है कि मैं संकलन पार कर रहा हूं। इस प्रकार यह ठीक हो सकता है या ठीक नहीं हो सकता है। मुझे लगता है कि प्रयास दो अलग-अलग फाइलों की तुलना में higer छोड़ दिया गया है क्योंकि सभी शीर्षलेख फ़ाइलों का आदान-प्रदान किया जाना चाहिए और इसलिए '# if' ब्लॉक के अंदर। मुझे खेद है, क्षमा करें। –

2

सबसे पहले, यह कहने के बिना जाना चाहिए कि आपको मूल्यांकन करना चाहिए (शायद प्रयोग करके) क्या यह करने योग्य है या नहीं। आपकी लुकअप टेबल आपके डेटा आकार और प्रोग्रामर प्रयास को बढ़ाने जा रही है, लेकिन आपको जिस रनटाइम की गति में वृद्धि की आवश्यकता हो सकती है या नहीं भी हो सकती है।

यदि आप अभी भी ऐसा करना चाहते हैं, तो मुझे नहीं लगता कि सी प्रीप्रोसेसर इसे सीधे कर सकता है, क्योंकि इसमें पुनरावृत्ति या रिकर्सन की कोई सुविधा नहीं है।

इस बारे में जाने का सबसे मजबूत तरीका तालिका के लिए सी स्रोत मुद्रित करने के लिए सी या किसी अन्य भाषा में एक प्रोग्राम लिखना होगा, और फिर उस प्रोग्राम को प्रीप्रोसेसर का उपयोग करके अपने प्रोग्राम में शामिल करना होगा। यदि आप make जैसे टूल का उपयोग कर रहे हैं, तो आप तालिका फ़ाइल जेनरेट करने के लिए नियम बना सकते हैं और अपनी .c फ़ाइल उस फ़ाइल पर निर्भर करती है।

दूसरी ओर, यदि आप वाकई कभी नहीं इस तालिका को बदलने के लिए जा रहे हैं कर रहे हैं, आप एक प्रोग्राम

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