मैं PROGMEM के साथ सरणी के बजाय पॉइंटर्स का उपयोग क्यों नहीं कर सकता हूं?


11

मैं वर्तमान में स्ट्रिंग स्टोरेज के लिए RAM के बजाय फ्लैश का उपयोग करने के लिए कुछ लाइब्रेरी बदल रहा हूं ताकि मैं किसी प्रोजेक्ट पर SRAM से बाहर न चला जाऊं।

पुस्तकालय में कुछ तार इस तरह से घोषित किए गए हैं:

const char *testStringA = "ABC";

यह अलग है कि मैं इसे सामान्य रूप से कैसे देखता हूं:

const char testStringB[] = "DEF";

हालांकि, मुझे लगता है कि घोषित होने पर इन दोनों को समतुल्य घोषित किया गया है। दोनों कोड में ठीक काम करते हैं।

मैंने इन्हें फ्लैश करने का प्रयास किया:

const prog_char *testStringC PROGMEM = "GHI";

मैंने तब पाया कि यह काम नहीं किया। यह मुद्रित होने पर gobbledegook का उत्पादन कर रहा था।

हालाँकि, निम्न सामान्य पैटर्न के बाद:

const prog_char testStringD[] PROGMEM = "JKL";

ठीक काम करता है।

मैं disassembly में देख सकता हूं:

00000068 <testStringC>:
  68:   04 01                                               ..

0000006a <_ZL11testStringD>:
  6a:   4a 4b 4c 00                                         JKL.

तो यह स्पष्ट है कि सूचक और PROGMEM परिणाम स्ट्रिंग / सरणी में आरंभीकृत नहीं हो रहे हैं।

ऐसा क्यों है?

उदाहरण कोड:

#include <avr/pgmspace.h>

const int BUFFER_LEN = 20;

const char *testStringA = "ABC";
const char testStringB[] = "DEF";
const prog_char *testStringC PROGMEM = "GHI";
const prog_char testStringD[] PROGMEM = "JKL";

void setup()
{
    Serial.begin(9600);
}

void loop()
{
    char buffer[BUFFER_LEN];

    Serial.println(testStringA);
    Serial.println(testStringB);

    strncpy_P(buffer, testStringC, BUFFER_LEN);
    Serial.println(buffer);

    strncpy_P(buffer, testStringD, BUFFER_LEN);
    Serial.println(buffer);

    delay(1000);

}

जवाबों:


6

वैसे, स्टैक ओवरफ्लो प्रश्न C के उत्तर में इस प्रश्न का बुद्धिमानी से उत्तर दिया गया है: char सूचक और सरणी के बीच अंतर

मूल रूप से, जिसे आप PROGMEM के रूप में घोषित कर रहे हैं,

const prog_char testStringD[] PROGMEM = "JKL";

सरणी और मेमोरी दोनों है जो इसे इंगित करता है, अर्थात, सरणी के तत्व, दोनों वर्तमान स्कोप स्टैक में। जबकि इसके साथ:

const prog_char* testStringC PROGMEM = "GHI";

आप एक निरंतर स्ट्रिंग के लिए PROGMEM पॉइंटर की घोषणा करते हैं जो स्मृति में कहीं और रह सकता है, लेकिन PROGMEM स्ट्रिंग के रूप में घोषित नहीं किया जाता है।

हालांकि मैंने उसका परीक्षण नहीं किया , लेकिन आपको घोषित करने का प्रयास करना चाहिए:

const prog_char* testStringC PROGMEM = F("GHI");

वास्तव में PROGMEM स्थान के भीतर इंगित स्ट्रिंग आवंटित करने के लिए। मुझे लगता है कि यह काम करना चाहिए, Arduino के F()मैक्रो का उपयोग करते हुए , जो वास्तव में सरणी घोषणा के समान परिणाम के लिए बहुत सारे बॉयलरप्लेट कोड जोड़ता है।

जैसा कि टिप्पणियों में कहा गया है, यदि वैश्विक संदर्भ में नहीं, तो PSTR()मैक्रो का उपयोग F()मैक्रो के बजाय किया जा सकता है ।

सरल बेहतर है: सरणी घोषणा का उपयोग करें, न कि सूचक एक का!

सीएफ कि अन्य जवाब , __flashक्वालीफायर एक तीसरा समाधान है ;-)


मैं पूरी तरह से "सरल बेहतर है" पर सहमत हूँ - सरणी बहुत दूर है। मैं हमेशा दिलचस्पी लेता हूं जब कुछ स्पष्ट नहीं होता है।
साइबरबर्गन

F () FlashStringHelper लौटाता है जो अनिवार्य रूप से समान है, लेकिन PSTR () का उपयोग करके ठीक काम करता है (जब तक आप किसी फ़ंक्शन के अंदर कास्ट लाते हैं)।
Cybergibbons

वास्तव में, मैंने वास्तव में पहले PSTR()मैक्रो का सुझाव दिया था, लेकिन F()सबमिट करने से पहले बदल दिया , क्योंकि आपके प्रश्न आपके क्यू में वैश्विक हैं, इसलिए मैंने उस के साथ रहना पसंद किया जो दोनों संदर्भों में काम करना चाहिए।
zmo

3

यह लाइन क्या है:

const prog_char *testStringC PROGMEM = "GHI";

SRAM में स्ट्रिंग में वर्णों को कॉपी करने के लिए प्रस्तावना कोड लिखना है, और फिर इस SRAM स्थान में फ्लैश में संग्रहीत पॉइंटर को इनिशियलाइज़ करता है । आपको सामान्य माध्यम से पॉइंटर को लोड करना होगा, और फिर पॉइंटर को हमेशा की तरह डिरेल करना होगा।

const char *str = pgm_read_word(&testStringC);
Serial.println(str);

यह रेखा:

const prog_char testStringD[] PROGMEM = "JKL";

फ़्लैश में वर्णों की सरणी बनाता है , जिससे आप इसे अपेक्षित रूप से एक्सेस कर सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.