2010-02-22 11 views
10

-link- से ANSI C व्याकरण मुझे सरणी घोषणाओं के लिए निम्नलिखित नियम दे:एएनएसआई-सी व्याकरण - जैसी सरणी घोषणाओं [*] एट Alii

:

(1) | direct_declarator '[' type_qualifier_list assignment_expression ']' 
(2) | direct_declarator '[' type_qualifier_list ']' 
(3) | direct_declarator '[' assignment_expression ']' 
(4) | direct_declarator '[' STATIC type_qualifier_list assignment_expression ']' 
(5) | direct_declarator '[' type_qualifier_list STATIC assignment_expression ']' 
(6) | direct_declarator '[' type_qualifier_list '*' ']' 
(7) | direct_declarator '[' '*' ']' 
(8) | direct_declarator '[' ']' 

अब मैं इन के बारे में कुछ सवाल हैं

  • क्या मैं (1) - (6) को छोड़कर (3) केवल सी 99 में उपयोग कर सकता हूं?
  • (4) और (5) के लिए क्या हैं? कीवर्ड 'स्थिर' मुझे भ्रमित करता है।
  • कहां उपयोग करें (6)?
  • क्या दो समारोह प्रोटोटाइप निम्नलिखित के बीच का अंतर है:

    void foo(int [*]); और

    void foo(int []);

धन्यवाद।

उत्तर

15

आप C89/90 में सरणी घोषणा के आकार भाग में टाइप क्वालीफायर या static का उपयोग नहीं कर सकते हैं। ये विशेषताएं सी 99 के लिए विशिष्ट हैं।

static सरणी घोषणा में संकलक बताता है कि आप का वादा करते हैं कि तत्वों की निर्दिष्ट संख्या हमेशा वास्तविक तर्क के रूप में पारित सरणी में मौजूद होगी। यह कंपाइलर्स को अधिक कुशल कोड उत्पन्न करने में मदद कर सकता है। यदि आप वास्तविक कोड में अपने वादे का उल्लंघन करते हैं (यानी एक छोटी सरणी पास करते हैं), व्यवहार अपरिभाषित है। उदाहरण के लिए,

void foo(int a[static 3]) { 
    ... 
} 

int main() { 
    int a[4], b[2]; 
    foo(a); /* OK */ 
    foo(b); /* Undefined behavior */ 
} 

* सरणी घोषणा के आकार हिस्से में समारोह प्रोटोटाइप घोषणाओं में ही प्रयोग किया जाता है।यह इंगित करता है कि सरणी में परिवर्तनीय लंबाई (वीएलए) है। उदाहरण के लिए, समारोह परिभाषा आप एक ठोस रन-टाइम आकार

void foo(int n, int a[n]) /* `a` is VLA because `n` is not a constant */ 
{ 
    ... 
} 

के साथ एक VLA उपयोग कर सकते हैं जब आप प्रोटोटाइप की घोषणा आप कर सकते हैं एक ही

void foo(int n, int a[n]); /* `a` is VLA because `n` is not a constant */ 

लेकिन यदि आप निर्दिष्ट नहीं करते पैरामीटर नाम (जो प्रोटोटाइप में ठीक है), आप पाठ्यक्रम के सरणी आकार के रूप में n का उपयोग नहीं कर सकते हैं। फिर भी, अगर आप अभी भी संकलक कि सरणी एक VLA होने जा रहा है यह बताने के लिए है, तो आप * उस उद्देश्य

void foo(int, int a[*]); /* `a` is VLA because size is `*` */ 

नोट के लिए उपयोग कर सकते हैं, कि एक 1 डी सरणी के साथ उदाहरण के लिए एक अच्छा एक नहीं है। यहां तक ​​कि अगर आप * छोड़ देते हैं और

void foo(int, int a[]); 

के रूप में ऊपर समारोह की घोषणा तो कोड को अभी भी है क्योंकि समारोह पैरामीटर घोषणाओं सरणी प्रकार में कार्य करेंगे, परोक्ष वैसे भी सूचक प्रकार के साथ बदल दिया है। लेकिन एक बार जब आप बहु-आयामी सरणी का उपयोग शुरू करते हैं, तो * का उचित उपयोग महत्वपूर्ण हो जाता है। उदाहरण के लिए, समारोह

void bar(int n, int m[n][n]) { /* 2D VLA */ 
    ... 
} 

के रूप में परिभाषित किया गया है अगर प्रोटोटाइप के रूप में लग सकता है

void bar(int n, int m[n][n]); /* 2D VLA */ 

या

void bar(int, int m[*][*]); /* 2d VLA */ 

उत्तरार्द्ध मामले पहले * में के रूप में छोड़ा जा सकता है इस प्रकार है (सरणी-से-पॉइंटर प्रतिस्थापन के कारण), लेकिन दूसरा * नहीं।

+0

मुझे लगता है कि यह जगह वास्तव में मायने रखती है जब आप 'f (int, int, int a [*] [*]) 'या जैसे ... – dmckee

+0

@dmckee: मैं बस इसे अपने उत्तर में जोड़ रहा था :) – AnT

+0

बहुत सारे लोग यहां के आसपास की लाइनों के साथ सोचते हैं। महान दिमाग और वह सब ... – dmckee

0

मेरा के & आर 2 एन (जो एएनएसआई मानक को कवर करता है और इसमें शामिल है) [*] या तो टेक्स्ट में या मानक में कुछ भी नहीं कहता है। न ही मानक में आधिकारिक व्याकरण को सिंटैक्स स्वीकार कर सकता हूं।

यह K& आर सी से संबंधित हो सकता है (हालांकि मुझे इसे याद नहीं है), हो सकता है कि एक सामान्य विस्तार हो या हो सकता है कि आखिरकार मानक नहीं बनाया गया।

मैं मानता हूं यह सरणी का आयाम स्पष्ट रूप से निर्दिष्ट नहीं करता है। लेकिन मैं बस अनुमान लगा रहा हूँ।


हम्म ... जीसीसी

#include <stdio.h> 

void f(int s, int a[*]); 

int main(void){ 
    int a[2] = {0}; 
    f(2,a); 
    return 0; 
} 

void f(int s, int a[]){ 
    int i; 
    for (i=0; i<s; ++i){ 
    printf("%d\n",a[i]); 
    } 
} 
एएनएसआई, C89 और C99 मोड में

स्वीकार करता है; -Wall के साथ भी कोई चेतावनी जारी नहीं है। ध्यान दें कि इसे फ़ंक्शन परिभाषा में [*] वाक्यविन्यास पसंद नहीं आया। -pedantic जोड़ने से यह c89 और ansi मोड में [*] वाक्यविन्यास के बारे में शिकायत करता है, लेकिन यह c99 मोड में स्वीकार करना जारी रखा।

+0

-Wall सभी सिंटैक्स के लिए चेतावनियां जारी नहीं करेगा कि सी 8 9 में जीएनयू एक्सटेंशन के रूप में माना जाता है। मुझे लगता है कि इसके लिए आपको भी आवश्यकता होगी। के एंड आर 2 एड। एएनएसआई सी 8 9 (अब आईएसओ सी 9 0) मानक के खिलाफ लिखा गया था, इसलिए सी 99 व्याकरण शामिल नहीं होगा। सी 99 परिवर्तनीय लंबाई सरणी और अन्य सरणी से संबंधित वाक्यविन्यास जोड़ता है। – Clifford

+0

फ़ंक्शन परिभाषा में [*] को पसंद नहीं करने के संबंध में, मानक कहता है [*] "एक परिवर्तनीय लंबाई सरणी प्रकार का निर्दिष्ट आकार, है जिसका उपयोग केवल * फ़ंक्शन प्रोटोटाइप * स्कोप" – Clifford

1

मुझे आशा है कि आप एक yacc विनिर्देश से सी व्याकरण सीखने की कोशिश नहीं कर रहे हैं !? आपके द्वारा पोस्ट किया गया लिंक the ISO C99 draft पर आधारित प्रतीत होता है। प्रासंगिक खंड 6.7.5.2 है। शब्द आर्केन है (लेकिन शायद yacc वाक्यविन्यास से भी कम!)

+0

के साथ घोषणाओं में किया जा सकता है, मैं ' मैं उस के साथ सी नहीं सीख रहा ;-) – tur1ng

+0

@ tur1ng: यह सिर्फ इतना है कि आपने कहा था "एएनएसआई सी व्याकरण- लिंक * मुझे * सरणी घोषणाओं के लिए निम्नलिखित नियम दें"। मेरा सुझाव है कि उन नियमों का उद्देश्य Yacc खपत के लिए था, न कि मानव उपभोग, और आईएसओ मानक मनुष्यों के लिए है (और yacc के लिए स्रोत दस्तावेज़ है)। और मैंने सिर्फ "सी" की बजाय "सी व्याकरण" कहा था; आप व्याकरण के जटिल ज्ञान के बिना एक कार्य स्तर पर सी सीख सकते हैं। शायद आप एक कंपाइलर या स्थैतिक विश्लेषक लिख रहे हैं? – Clifford

+0

ओह क्षमा करें, मैं बहुत तेज़ पढ़ रहा था। हां यह एक स्थिर विश्लेषक के लिए है। – tur1ng

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