2010-02-18 14 views
9

पर शुरू होने से पहले एक इंडेक्स पर सरणी शुरू करना संभव नहीं है ... आईई। आपके पास 35 तत्वों में से एक [35] है, अब मैं 100 से शुरू होने पर इंडेक्स करना चाहता हूं, इसलिए संख्याएं [100], एक [101], ... एक [134] है, क्या यह संभव है ?एरे इंडेक्सिंग 0

मैं बोर्ड के लिए "मेमोरी मैप" उत्पन्न करने का प्रयास कर रहा हूं और मेरे पास SRAM [10000] नामक एक सरणी होगी और दूसरा उदाहरण के लिए ब्रैम [5000] कहा जाता है, लेकिन "स्मृति" दृश्यता में वे हैं संगत, आईई बीआरएएम एसआरएएम के ठीक बाद शुरू होता है, इसलिए यदि मैं 11000 मेमोरी लोकेशन को इंगित करने का प्रयास करता हूं तो मैं इसे पढ़ता हूं कि यह 10000 से अधिक है और फिर इसे ब्रैम में भेज दें।

यह टाइप करते समय मुझे एहसास हुआ कि मुझे लगता है कि मैं संख्या से 10K घटा सकता हूं और इसे ब्रैम में भेज सकता हूं, लेकिन तर्क के लिए, क्या यह ब्रैम को 11000 से गुजरने वाला सूचकांक संभव है?

किसी भी मदद के लिए धन्यवाद।

ठीक करने के लिए अपडेट किया गया एक [34] एक [134]

अतिरिक्त जानकारी के लिए अपडेट किया गया करने के लिए: वास्तविक वास्तुकला कार्यान्वयन के लिए मैं हो जाएगा में,/SRAM और ब्रैम के लिए इतना के बीच एक अंतर हो सकता है कर सकते हैं उदाहरण के लिए पता 11008 मेमोरी मैप में दिखाई नहीं दे सकता है, इस प्रकार स्मृति से भरा एक विशाल सरणी लिख रहा है, फिर यह "विभाजन" काम करेगा, लेकिन मुझे अभी भी यह निर्धारित करने के लिए तर्क करना होगा कि यह "स्राम और ब्रैम" की सीमाओं के भीतर है या नहीं "। जो मैं पहले स्थान से बचाना चाहता था।

+1

किस प्रकार का अनुक्रम 100 है, 101 ... 34? : ओ और नहीं, सूचकांक हमेशा 0 से शुरू होता है। आपको कुछ गणित करने की आवश्यकता होगी। – GManNickG

+0

मैं अनुमान लगा रहा हूं [100], एक [101], ... एक [34] एक [100] होना चाहिए, एक [101], ... एक [134]। क्या कोई इसे संपादित कर सकता है? –

+0

माफ करना, मैंने वहां 1 को याद किया, मेरा मतलब 100, 101, ... 134 ... क्षमा करें – onaclov2000

उत्तर

16

क्या यह एक इंडेक्स पर शून्य नहीं है, शून्य नहीं है ... आईई। आपके पास 35 तत्वों में से एक सरणी है [35], अब मैं 100 से शुरू होने पर इंडेक्स करना चाहता हूं, इसलिए संख्याएं [100], एक [101], ... एक [134], क्या यह संभव है?

नहीं, आप सी में ऐसा नहीं कर सकते हैं। Arrays हमेशा शून्य से शुरू होते हैं। सी ++ में, आप अपनी खुद की कक्षा लिख ​​सकते हैं, OffsetArray कहें और सूचकांक से ऑफ़सेट घटाने के दौरान अंतर्निहित सरणी तक पहुंचने के लिए [] ऑपरेटर को अधिभारित करें।

मैं बोर्ड के लिए "मेमोरी मैप" उत्पन्न करने का प्रयास कर रहा हूं और मेरे पास SRAM [10000] नामक एक सरणी होगी और दूसरा उदाहरण के लिए ब्रैम [5000] कहा जाता है, लेकिन "स्मृति" दृश्यता में वे ' फिर से, आईई बीआरएएम एसआरएएम के ठीक बाद शुरू होता है, इसलिए यदि मैं 11000 मेमोरी लोकेशन को इंगित करने का प्रयास करता हूं तो मैं इसे पढ़ता हूं कि यह 10000 से अधिक है और फिर इसे ब्रैम में भेज दें।

आप कुछ इस तरह की कोशिश कर सकते: अब

char memory[150000]; 
char *sram = &memory[0]; 
char *bram = &memory[100000]; 

, जब आप का उपयोग sram[110000] आप "bram में" कुछ है कि तक पहुँचने हो जाएगा

+2

+1, वास्तव में यह संपूर्ण स्मृति मानचित्र और 'sran' और' bram' तक पहुंचने के लिए 'स्मृति' का उपयोग करके विशिष्ट उप-प्रोजेक्ट –

+0

तक पहुंचने में समझ में आता है सामान्य रूप से मुझे यह विचार पसंद है, लेकिन मैं अभी भी वहां " ऊपरी बाउंड "लेकिन मुझे लगता है कि उपयोगकर्ता परिभाषित किया जा सकता है और होगा। – onaclov2000

+2

मैक्रो का उपयोग करने के बारे में: '# परिभाषित ARRAY_OFFSET ((x) - 100)' और सरणी को एक्सेस करना जैसे 'स्मृति [ARRAY_OFFSET (100)] '। मैक्रो के पास कुछ भ्रम है, लेकिन यह सी और सी ++ दोनों के साथ संगत है। –

1

सी में नहीं, आपको अंकगणित स्वयं करना है। शायद विचित्र कार्य-आस-पास हैं जो ज्यादातर समय काम करते हैं, जैसे कि एक नया सूचक जो BRAM-11000 है और इसके बजाय इसका उपयोग कर रहा है।

12

सी ++ इस संबंध में सी से थोड़ा अधिक प्रदान करता है। घटाव करने के लिए आप operator[] को अधिभारित कर सकते हैं, और अगर आप किसी त्रुटि की रिपोर्ट करना चाहते हैं (उदा।, अपवाद फेंक दें) यदि सबस्क्रिप्ट सीमा से बाहर है।

+1

मुझे आशा है कि आप इसे एक संभावित समाधान के रूप में इंगित कर रहे हैं और इसकी अनुशंसा नहीं कर रहे हैं। :-) [] ऑपरेटर को अधिभारित करना अनावश्यक जटिलता की ओर जाता है। –

+1

@ स्टेव: वास्तव में नहीं। ऑपरेटरों को ओवरलोड करने के लिए जो वे आम तौर पर करते हैं वे भ्रमित नहीं होते हैं। फ़ाइल में 'ए + बी' लिखना 'ए' और' बी 'बनाना भ्रमित है। '[]' अनुक्रमण के लिए है। उस ने कहा, ऑफसेट जोड़ने और अंतर्निर्मित 'ऑपरेटर [] 'का उपयोग करके एक नया सूचक प्राप्त करना शायद आसान है। किसी भी जटिल इंडेक्सिंग योजना के लिए, 'ऑपरेटर []' के साथ एक रैपर वर्ग बनाना निश्चित रूप से सबसे साफ है। – GManNickG

+0

कक्षाओं के लिए कोई अंतर्निहित 'ऑपरेटर [] 'नहीं है जब तक कि आप एक प्रदान न करें। – kennytm

6

नहीं - जैसा कि आप वीबी 6 जैसी घोषणा में निचले बाध्य को संशोधित नहीं कर सकते हैं।

हाँ - में के रूप में आप की तरह

int a[35]; 
int* actual_a = a-100; 
printf("%d", actual_a[101]); 
... 

क्योंकि x[a]*(x+a) के बराबर है चाल कर सकते हैं। यह बेहद अनुशंसित है।

+7

पॉइंटर 'ए -100' के रूप में _undefined behaviour_ में परिणाम बनाने के रूप में, मैं बस "अत्यधिक अनुशंसित" कहने से आगे जाऊंगा। –

+0

मैं देखता हूं कि परिणाम कैसे संग्रहित करना यूबी है। लेकिन अभिव्यक्ति में '(ए -100) [101]', उप-अभिव्यक्ति पहले से ही यूबी का कारण बन जाएगी? सी के पुनर्मूल्यांकन मूल्यांकन में बहुत अक्षांश है। इसलिए, यह अभिव्यक्ति '* (ए -100 + 101)', '* (ए + 101-100)' और '* (ए + (101-100)) दिखाई देता है, सभी समान हैं, क्योंकि सभी को फिर से किया जा सकता है एक ही परिणाम। लेकिन चूंकि उत्तरार्द्ध यूबी नहीं है, ऐसा लगता है कि कोई भी यूबी नहीं होना चाहिए। कारण मुझे आश्चर्य है क्योंकि एक मैक्रो '# परिभाषित ACTUAL_A (a-100)' इस फ़ॉर्म में विस्तारित होगा। – MSalters

7

आप मैक्रो के साथ धोखा कर सकते हैं:

int myarray[35]; 

#define a (myarray - 100) 

a[100] = 0; 

एक सूचक का भी उपयोग किया जा सकता है।

1

यह करने के लिए सबसे आसान तरीका:

आपके पास:

int *array = memory ; // starts with 0; 
array-= 1000 ; // now array[1000] is 0 

सी ++ में सिर्फ वर्ग के साथ operator[]

+1

शायद यह अधिकांश सी कंपेलरों में काम करेगा लेकिन यह मानक द्वारा गारंटी नहीं है। केवल एक सरणी के भीतर पॉइंटर्स या अंत में एक की गारंटी है। – paxdiablo

+0

@paxdiablo: चलो यहाँ pedantic और तकनीकी मिलता है। क्या सी मानक किसी सरणी के बाहर पॉइंटर्स की * dereferencing * की गारंटी नहीं देता है या क्या यह सरणी सीमाओं से परे * पॉइंटर अंकगणित * की गारंटी नहीं देता है? मेरे अनुभव में, कोई व्यक्ति पहले यूएआरटी रजिस्टर में पॉइंटर को परिभाषित कर सकता है और अन्य संगत रजिस्टरों के लिए पॉइंटर समायोजित कर सकता है, भले ही एक सरणी कभी घोषित न हो। –

+0

पॉइंटर अंकगणित की गारंटी है _ और अंत में एक अंत सहित; अव्यवस्था केवल वास्तविक सरणी तत्वों के लिए गारंटीकृत है। अंतर यह है कि आप पॉइंटर को डिफ्रेंस करने से पहले यह निर्धारित करने के लिए पॉइंटर अंकगणित का उपयोग कर सकते हैं कि आपने सरणी के अंत को मारा है या नहीं। यूएआरटी रजिस्ट्रार के पॉइंटर्स हमेशा यूबी होते हैं। – MSalters

0

प्वाइंटर बना सकते हैं और सरणियों सी में बहुत समान हैं, तो आप easilly कर सकता है कुछ

element SRAM_MEM[10000]; 
element BRAM_MEM[5000]; 

element* SRAM = SRAM_MEM; 
element* BRAM = BRAM_MEM-10000; 

BRAM[10001] = 0; // sets the first element of BRAM_MEM 
4

आप बिल्कुल बिल्कुल स्पष्ट नहीं हैं कि आप कैसे बिल्कुल स्पष्ट हैं इन सरणियों का उपयोग करना चाहते हैं, लेकिन पर्याप्त अपनी आसान एक भी सन्निहित सरणी कि दो अलग अलग सरणियों होने के लिए प्रकट हो सकते हैं स्थापित करने के लिए:

int ram[15000]; 
int * sram=&ram[0]; 
int * bram=&ram[10000]; 

मैं सिर्फ बनाने के लिए & foo [XXX] अंकन इस्तेमाल किया यह स्पष्ट है कि तुम क्या ' कर रहा हूँ वैसे भी, अब आप रैम का उपयोग पूरे सरणी में कहीं भी इंडेक्स करने के लिए कर सकते हैं, या विशेष भागों में इंडेक्स के लिए एसआरएम और ब्रैम का उपयोग कर सकते हैं।

+0

एक डरावना विचार: समाधान अपरिभाषित स्मृति के क्षेत्रों तक पहुंच की अनुमति देता है या यह स्मृति प्रदान करता है जहां कोई भी नहीं है। –

+2

ठीक है, हाँ और नहीं। यह सी में मानक सरणी अनुक्रमण के मुकाबले स्मृति के लिए और अधिक अप्रतिबंधित पहुंच प्रदान नहीं करता है बशर्ते कि कोई सीमा से बाहर नहीं है, एक सामान्य सरणी के समान ही सुरक्षित है। – swestrup

0

बस एक वैरिएबल है जो ऑफसेट को ध्यान में रखता है। यहां तक ​​कि यदि संभव हो, तो एक सरणी जो परंपरागत 0 पर शुरू नहीं होती है, वह बहुत ही अपठनीय होगी।

8

मुझे 'विशेषज्ञ सी प्रोग्रामिंग - दीप सी सीक्रेट्स' पुस्तक में पढ़ना याद है, पीटर वान डेर लिंडेन सोचने वाले सरणी ऑफ़सेट में संकलक को मूर्ख बनाने के लिए एक चाल का खुलासा करते हैं ... सैद्धांतिक रूप से चाल पूरा हो सकती है, मैं करता हूं नहीं मेरे साथ पुस्तक है, लेकिन इसी समय, मैं इसे पढ़ने याद ... यह पोर्टेबल नहीं है और अपरिभाषित व्यवहार का उत्पादन हो सकता ...

संपादित करें: यहाँ खंड 6.17 देखें सी पूछे जाने वाले प्रश्न पर। चेतावनी: पोर्टेबल और अपरिभाषित व्यवहार नहीं! यहां source से उद्धरण के लिए।

 
6.17: Here's a neat trick: 
     if I write int realarray[10]; 
     int *array = &realarray[-1]; 
I can treat "array" as if it were a 1-based array. A: Although this technique 
is attractive (and was used in old editions of the book _Numerical Recipes in C_), 
it is not strictly conforming to the C Standard. Pointer arithmetic is defined 
only as long as the pointer points within the same allocated block of memory, 
or to the imaginary "terminating" element one past it; otherwise, the behavior 
is undefined, *even if the pointer is not dereferenced*. The code above could 
fail if, while subtracting the offset, an illegal address were generated 
(perhaps because the address tried to "wrap around" past the beginning of some 
memory segment). 

References: K&R2 Sec. 5.3 p. 100, Sec. 5.4 pp. 102-3, Sec. A7.7 pp. 205-6; 
ISO Sec. 6.3.6; Rationale Sec. 3.2.2.3. 

Read more: http://www.faqs.org/faqs/C-faq/faq/#ixzz0ftyqHOvm 

उम्मीद है कि इससे मदद मिलती है।

+0

भले ही यह एक भाषा परिप्रेक्ष्य से अपरिभाषित व्यवहार है, फिर भी आधुनिक कंप्यूटरों को उनकी याददाश्त के तरीके के कारण तकनीकी रूप से विश्वसनीय रूप से काम करना चाहिए। एकमात्र खतरा यह है कि अनुकूलक यह बताता है कि आप अपरिभाषित व्यवहार का आह्वान कर रहे हैं, और अपने कोड को दूर कर सकते हैं। – cmaster

+0

कहां कहता है 'तकनीकी रूप से काम विश्वसनीय'? यह अकेले उस कारण के लिए अपरिभाषित व्यवहार है, यानी हर रोज इस्तेमाल नहीं किया जाता है, और प्रश्न में सी कंपाइलर और पर्यावरण भी स्वयं पर निर्भर करता है। भले ही कोड ऑप्टिमाइज़ हो या नहीं, भले ही कोई गारंटी न हो। यह कुछ अन्य स्मृति भाग को तोड़ सकता है, segfault, clobber। उस तरह के कोड का उपयोग करके, कोड समीक्षकों के बीच अलार्म बढ़ाएंगे और चिंता का कारण भी होगा - यानी कोड गंध करता है। – t0mm13b

+0

ठीक है, कुछ असेंबलर कोडिंग करें, और आपको पता चलेगा कि यह तकनीकी रूप से विश्वसनीय क्यों है। पॉइंटर्स हुड के तहत 32 या 64 बिट पूर्णांक से अधिक कुछ नहीं हैं, हार्डवेयर हस्ताक्षरित और हस्ताक्षरित (क्योंकि इसकी आवश्यकता नहीं है) के बीच भी अंतर नहीं है। पॉइंटर अंकगणित में शामिल कुछ भी हस्ताक्षरित पूर्णांक अंकगणितीय के समान है। – cmaster

1

कडाई के इस समाधान आप एक सूचकांक 0 से अलग से शुरू एक सरणी को परिभाषित loet नहीं है, लेकिन आप अपनी स्मृति इस तरह की घोषणा कर सकते हैं: कि स्मृति सटा हुआ है

typedef union 
{ 
    unsigned char all[15000]; 
    struct 
    { 
     unsigned char sram[10000]; 
     unsigned char bram[5000]; 
    }; 
} memory; 

इस आशय व्यक्त करता है , और यह 2 भागों में विभाजित है। ध्यान दें कि आपको bram और sram के संरेखण से सावधान रहना चाहिए, #pragma pack(1) आवश्यक हो सकता है।

0

शायद आप संघ का उपयोग कर सकते हैं?

#pragma pack(0) 
union 
{ 
    char array[15000]; 
    struct { char sram[10000]; char bram[5000]; } map; 
} combination; 

वे शारीरिक रूप से संगत हैं।यदि आप 'सरणी' तक पहुंचते हैं तो यह ऑफ़सेट

पर आधारित ब्रैम या स्राम में जाएगा, आपको कंपाइलर को शब्द सीमाओं पर संरचना सदस्यों को संरेखित करने के लिए कहने के लिए प्रज्ञा की आवश्यकता नहीं है। यह नक्शा संरचना के दो हिस्सों के बीच अंतरिक्ष के कई बाइटों को रोकता है।

2

के रूप में दूसरों का उल्लेख किया है, तो आप तकनीकी रूप से प्राप्त कर सकते हैं इस तरह सूचक अंकगणित लागू द्वारा आप क्या चाहते हैं:

int* myArray = malloc((upperBound - lowerBound) * sizeof(*myArray)); 
myArray -= lowerBound; 
... 
for(int i = lowerBound; i < upperBound; i++) { 
    myArray[i]; 
} 

इस दोषरहित -O0 के साथ काम करते हैं, यह देखने के एक बिंदु से भाषा अपरिभाषित व्यवहार है। मशीन, हालांकि, इस पर पूरी तरह से कोई आपत्ति नहीं है, मशीन को पॉइंटर अंकगणित शामिल है uintptr_t के साथ किसी भी हस्ताक्षरित पूर्णांक अंकगणित जैसा ही है। इस प्रकार, इस दृष्टिकोण के लिए एकमात्र खतरा अनुकूलक है।

अब, आप कोड को दो अलग-अलग संकलन इकाइयों में विभाजित करके आसानी से अनुकूलक को हरा सकते हैं, i। ई। समारोह

int* fancyIntArray(size_t lowerBound, size_t upperBound) { 
    return intMalloc(upperBound - lowerBound) - lowerBound; 
} 

के साथ एक "ग" फ़ाइल है और एक अलग "ग" फ़ाइल में समारोह intMalloc() डाल: अब

int* intMalloc(size_t size) { 
    return malloc(size_t*sizeof(int)); 
} 

, आप सुरक्षित हैं, क्योंकि जब अनुकूलक fancyIntArray() में पॉइंटर अंकगणितीय को देखता है, यह नहीं जानता कि intMalloc() रिटर्न के सामने कोई आवंटित स्मृति नहीं है, क्योंकि यह intMalloc() के बारे में कुछ भी नहीं जानता है। इस प्रकार, इसे आपके कोड को बरकरार रखने के लिए मजबूर होना पड़ता है।

और, ज़ाहिर है, आपको विभिन्न ".c" फ़ाइलों को संकलित करने के लिए स्वतंत्र कंपाइलर कॉल का उपयोग करना चाहिए, ताकि अनुकूलक वास्तव में intMalloc() के बारे में कुछ भी कम नहीं कर सके।

+0

ऑप्टिमाइज़र पहले उदाहरण के कोड पर वास्तव में क्या कर सकता है? –

+1

@MichaelLehn ऑप्टिमाइज़र का खतरा यह है कि इसे * कोड * निकालने की अनुमति है जिसमें से यह साबित हो सकता है कि यह अपरिभाषित व्यवहार का आह्वान करता है। अर्थात। यह अपरिभाषित व्यवहार को कुछ भी करने के व्यवहार के साथ प्रतिस्थापित नहीं कर सकता है। स्मार्ट लगता है, लेकिन यह काफी कुछ जाल बनाता है जहां लोग अनजाने में अपरिभाषित व्यवहार का आह्वान करते हैं - पहले उदाहरण में, यह केवल पूरे लूप को हटा सकता है। इसलिए, यदि आप वास्तव में कुछ ऐसा करना चाहते हैं जो तकनीकी रूप से अपरिभाषित व्यवहार है, कम से कम सुनिश्चित करें कि अनुकूलक क्या कर रहा है उसे कम करने में सक्षम नहीं है। – cmaster

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