c रखण Int x[n] गलत क्यों है जहाँ n एक कास्ट वैल्यू है?




मुस्लिम जाति लिस्ट obc (5)

क्यों int x[n] गलत है जहां n एक const वैल्यू है?

n एक स्थिरांक नहीं है। const केवल वादा करता है कि n एक 'रीड-ओनली' वैरिएबल है जिसे प्रोग्राम एक्जीक्यूशन के दौरान संशोधित नहीं किया जाना चाहिए।
ध्यान दें कि c , सी ++ के विपरीत, const योग्य चर स्थिर नहीं हैं। इसलिए, घोषित सरणी एक चर लंबाई सरणी है।
आप वैरिएबल की लंबाई सरणियों को आरंभ करने के लिए इनिशलाइज़र सूची का उपयोग नहीं कर सकते हैं।

C11-§6.7.9 / 3:

आरंभिक होने वाली इकाई का प्रकार अज्ञात आकार या पूर्ण ऑब्जेक्ट प्रकार का एक सरणी होगा जो कि एक चर लंबाई सरणी प्रकार नहीं है

n को स्थिर बनाने के लिए आप #define या enum का उपयोग कर सकते हैं

#define n 5
int x[n] = { 1,1,3,4,5 };   

https://code.i-harness.com

मैं नहीं समझ सकता कि ऐसा करना गलत क्यों है:

const int n = 5; 
int x[n] = { 1,1,3,4,5 };

हालांकि n पहले से ही एक कॉस्ट वैल्यू है।

ऐसा करना GNU कंपाइलर के लिए सही प्रतीत होता है:

const int n = 5;
int x[n]; /*without initialization*/

मुझे C99 के वीएलए सुविधा के बारे में पता है और मुझे लगता है कि यह संबंधित है जो चल रहा है लेकिन मुझे पृष्ठभूमि में क्या हो रहा है, इसके बारे में कुछ स्पष्टीकरण की आवश्यकता है।


क्या आपका कोड myfunc() से अलग है:

void myfunc(const int n) { 
    int x[n] = { 1,1,3,4,5 };
    printf("%d\n", x[n-1]);
    *( (int *) &n) = 17;    //  Somewhat less "constant" than hoped...
    return ;
}

int main(){
    myfunc(4);
    myfunc(5);
    myfunc(6);  //  Haven't actually tested this.  Boom?  Maybe just printf(noise)?
    return 0;
}

क्या वास्तव में यह सब स्थिर है? आपको कितना स्थान लगता है कि संकलक को x[] लिए आवंटित किया जाना चाहिए (क्योंकि यह ऐसा करने के लिए संकलक का काम है)?

जैसा कि अन्य ने बताया है, सीवी-क्वालीफायर const मतलब "एक ऐसा मूल्य नहीं है जो संकलन के दौरान और उसके बाद सभी समय के लिए स्थिर हो।" इसका अर्थ है "एक मान जिसे स्थानीय कोड को बदलना नहीं है (हालांकि यह हो सकता है)"।


भले ही n एक const , आप इसका उपयोग किसी सरणी के आकार को परिभाषित करने के लिए नहीं कर सकते, जब तक कि आप वीएलए बनाना नहीं चाहते। हालाँकि, आप एक VLA इनिशियलाइज़ करने के लिए इनिशियलाइज़र सूची का उपयोग नहीं कर सकते हैं।

निश्चित आकार की सरणी बनाने के लिए मैक्रो का उपयोग करें।

#define ARRAY_SIZE 5

int x[ARRAY_SIZE] = { 1,1,3,4,5 };

यदि आप किसी सरणी को प्रारंभिक रूप से आरंभ कर रहे हैं, तो संकलक को सरणी का आकार बताने देने के लिए यह अधिक सुरक्षित, सुरक्षित और अधिक बनाए रखने योग्य है:

int x[] = { 1,1,3,4,5 };
const int n = sizeof(x) / sizeof(*x) ; 

फिर सरणी आकार बदलने के लिए आपको केवल मिलान करने के लिए आकार और प्रारंभिक सूची को बदलने के बजाय, आरंभकर्ताओं की संख्या को बदलना होगा। विशेष रूप से उपयोगी है जब कई इनिशियलाइज़र होते हैं।


याद रखने वाली महत्वपूर्ण बात यह है कि const और "स्थिर" का अर्थ दो अलग-अलग चीजें हैं।

const कीवर्ड का अर्थ वास्तव में "केवल पढ़ने के लिए" है। एक स्थिरांक एक संख्यात्मक शाब्दिक है, जैसे कि 42 या 1.5 (या एक गणना या वर्ण स्थिर)। एक स्थिर अभिव्यक्ति एक विशेष प्रकार की अभिव्यक्ति है जिसका संकलन समय पर किया जा सकता है, जैसे कि 2 + 2

तो एक घोषणा दी:

const int n = 5;

अभिव्यक्ति n ऑब्जेक्ट के मूल्य को संदर्भित करता है, और इसे एक स्थिर अभिव्यक्ति के रूप में नहीं माना जाता है। एक विशिष्ट संकलक n सन्दर्भ को अनुकूलित करेगा, इसे उसी कोड के द्वारा प्रतिस्थापित करेगा जो इसे शाब्दिक 5 लिए उपयोग करेगा, लेकिन इसकी आवश्यकता नहीं है - और इसके लिए नियम कि अभिव्यक्ति स्थिर है भाषा द्वारा निर्धारित की जाती है, की चतुराई से नहीं वर्तमान संकलक।

const (केवल पढ़ने के लिए) और स्थिर (संकलन समय पर मूल्यांकन) के बीच अंतर का एक उदाहरण है:

const size_t now = time(NULL);

const कीवर्ड का मतलब है कि आपको इसकी शुरुआत के बाद के मूल्य को संशोधित करने की अनुमति नहीं है, लेकिन time(NULL) के मूल्य को स्पष्ट रूप से चलाने के समय तक गणना नहीं की जा सकती है।

तो यह:

const int n = 5;
int x[n];

C से अधिक वैध नहीं है क्योंकि यह const कीवर्ड के बिना होगा।

भाषा एक स्थिर अभिव्यक्ति के रूप में n (और IMHO शायद चाहिए) का मूल्यांकन कर सकती है ; यह सिर्फ इस तरह से परिभाषित नहीं है। (C ++ में ऐसा नियम है; C ++ मानक या गोर विवरण के लिए एक अच्छा संदर्भ देखें।)

यदि आप मान 5 साथ नामांकित स्थिरांक चाहते हैं, तो मैक्रो को परिभाषित करने का सबसे आम तरीका है:

#define N 5
int x[N];

एक अन्य दृष्टिकोण एक निरंतरता को परिभाषित करना है:

enum { n = 5 };
int x[n];

गणन स्थिरांक निरंतर अभिव्यक्ति हैं, और हमेशा प्रकार के int (जिसका अर्थ है कि यह विधि int अलावा अन्य प्रकार के लिए काम नहीं करेगी)। और यह यकीनन enum तंत्र का दुरुपयोग है।

1999 मानक के साथ शुरू होने पर, एक सरणी को गैर-स्थिर आकार के साथ परिभाषित किया जा सकता है; यह एक वीएलए, या चर-लंबाई सरणी है। इस तरह के सरणियों को केवल ब्लॉक स्कोप में अनुमति दी जाती है, और इसमें इनिशियलाइज़र नहीं हो सकते हैं (क्योंकि कंपाइलर यह जांचने में असमर्थ है कि इनिशलाइज़र में तत्वों की सही संख्या है)।

लेकिन आपका मूल कोड दिया गया है:

const int n = 5; 
int x[n] = { 1,1,3,4,5 };

आप संकलक को इनिलाइज़र से लंबाई का अनुमान लगा सकते हैं:

int x[] = { 1,1,3,4,5 };

और फिर आप सरणी के आकार से लंबाई की गणना कर सकते हैं:

const int x_len = sizeof x / sizeof x[0];




c99