क्यों ऑटो एक = 1; C में संकलन?


125

कोड:

int main(void)
{
    auto a=1;
    return 0;
}

MS Visual Studio 2012 संकलक द्वारा त्रुटियों के बिना संकलित किया जाता है, जब फ़ाइल में .c एक्सटेंशन होता है। मैंने हमेशा सोचा है कि जब आप .c एक्सटेंशन का उपयोग करते हैं, तो संकलन सी सिंटैक्स के अनुसार होना चाहिए, न कि सी ++। इसके अलावा, जहां तक ​​मुझे पता है कि ऑटो बिना किसी प्रकार के C ++ 11 के बाद से केवल C ++ में अनुमति दी जाती है , जहां इसका अर्थ है कि टाइप इनिशियलाइज़र से घटाया गया है।

इसका मतलब यह है कि मेरा संकलक सी से चिपका नहीं है, या क्या सी-भाषा में कोड वास्तव में सही है?


8
या तो आप C ++ मोड के साथ संकलित करते हैं (संभव) या MS अभी भी अंतिम सहस्राब्दी में अटका हुआ है। अंतर्निहित int1999 में सी मानक से हटा दिया गया
जेन्स Gustedt

16
@JensGustedt MSVC ++ केवल C89 (और C99 के कुछ फीचर्स) का समर्थन करता है। यह C ++ कंपाइलर का अधिक है।
ntoskrnl

3
@ ब्रैंडिन: / वॉल ऑप्शन के साथ यह चेतावनी देता है C4431, यह कहते हुए कि एक प्रकार का विनिर्देशक गायब है और सी में डिफ़ॉल्ट डिफ़ॉल्ट अब समर्थित नहीं है (देखें जेन्स की टिप्पणी)। यह विरोधाभास का एक सा है क्योंकि जाहिर है यह संकलक इसका समर्थन करता है ...
lee77

4
@JensGustedt उस उपाय के द्वारा, GCC 4.7, 2012 को रिलीज़ किया गया (और बाद के संस्करणों में भी, मुझे संदेह है - मेरे पास वे हाथ नहीं हैं) "अंतिम सहस्राब्दी में अटक गया है"। यह ओपी कोड को बिना किसी झंडे की सूचना दिए भी संकलित करता है।

3
@ डेलनान, मैं कम से कम यह मान रहा था कि ओपी ने चेतावनी के स्तर को बदल दिया है। मैं स्पष्ट रूप से गलत था। और एक मायने में यह सच है, जीसीसी भी अभी भी वहां अटका हुआ है, क्योंकि उनके पास अभी भी डिफ़ॉल्ट रूप में सी 99 (या एक संस्करण) नहीं है। क्लैंग बिना झंडे के भी निर्माण के बारे में चेतावनी देता है।
जेन्स गस्टेड

जवाबों:


240

autoएक पुराना C कीवर्ड है जिसका अर्थ है "स्थानीय गुंजाइश"। auto aके रूप में ही है auto int a, और क्योंकि स्थानीय गुंजाइश एक फ़ंक्शन के अंदर घोषित एक चर के लिए डिफ़ॉल्ट है, यह int aइस उदाहरण में भी समान है ।

यह कीवर्ड वास्तव में सी के पूर्ववर्ती बी से एक बचे हुए हैं, जहां कोई आधार प्रकार नहीं थे: सब कुछ था int, सूचक int, की सरणी int(*) घोषणाएं autoया तो होंगी या extrn[sic]। C को "सब कुछ है int" एक डिफ़ॉल्ट नियम के रूप में विरासत में मिला है , इसलिए आप पूर्णांकों की घोषणा कर सकते हैं

auto a;
extern b;
static c;

आईएसओ सी को इससे छुटकारा मिल गया, लेकिन कई कंपाइलर्स अभी भी इसे पिछड़ी संगतता के लिए स्वीकार करते हैं। यदि यह अपरिचित लगता है, तो आपको महसूस करना चाहिए कि संबंधित नियम काम में है

unsigned d;  // actually unsigned int

जो आधुनिक कोड में अभी भी सामान्य है।

C ++ 11 ने कीवर्ड का पुन: उपयोग किया, जो कि यदि कोई C ++ प्रोग्रामर मूल अर्थ के साथ उपयोग कर रहा है, तो इसके प्रकार के अनुमान के लिए। यह ज्यादातर सुरक्षित है क्योंकि intC से "सब कुछ है " नियम पहले ही C ++ 98 में हटा दिया गया था; केवल एक चीज जो टूटती है auto T a, वह है जो कोई भी वैसे भी उपयोग नहीं कर रहा था। ( भाषा के इतिहास पर उनके पत्रों में कहीं , स्ट्रॉन्स्ट्रुप इस पर टिप्पणी करता है, लेकिन मुझे अभी इसका सटीक संदर्भ नहीं मिल सकता है।)

(*) B में स्ट्रिंग हैंडलिंग दिलचस्प था: आप intप्रत्येक सदस्य में कई वर्णों के सरणियों का उपयोग और पैक करेंगे। बी वास्तव में अलग वाक्यविन्यास के साथ बीसीपीएल था ।


7
नहीं, यह 1999 के बाद से कानूनी नहीं है। कोई भी आधुनिक सी संकलक इसके लिए अनुमति नहीं देता है।
जेन्स गुस्टेड

18
@JensGustedt VS आधुनिक C संकलक प्रदान करने का दावा नहीं करता है। सभी दिखावे से, सी कंपाइलर पर काम कई साल पहले बंद हो गया; वे केवल इसकी आपूर्ति करते हैं ताकि लोग विरासत कोड संकलित कर सकें। (और निश्चित रूप से, किसी भी सभ्य आधुनिक सी कंपाइलर के पास विरासत कोड का समर्थन करने के विकल्प होंगे। K & R C. के लिए एक विकल्प भी शामिल है)
जेम्स कांजे

23
@JensGustedt: क्या आपको यकीन है? GCC और Clang दोनों ने C99 मोड में इसके बारे में चेतावनी दी है, लेकिन वे इसे छोड़कर एक त्रुटि नहीं मानते हैं -Werror
फ्रेड फू

2
@ लार्समैन, हाँ, 6.7.2 में इसके लिए एक स्पष्ट बाधा है: प्रत्येक घोषणा में कम से कम एक प्रकार का निर्दिष्टकर्ता निर्दिष्टकर्ता में दिया जाएगा ...
जेन्स गुस्तेद

40
@JensGustedt - नहीं नहीं, यह 1999 से कानूनी सी नहीं है। कोई भी आधुनिक सी संकलक इसके लिए अनुमति नहीं देता है। पहला कथन सही है; यह 1999 से अवैध है। IMHO, दूसरा कथन गलत है। किसी भी सभ्य आधुनिक सी कंपाइलर को इसके लिए अनुमति देनी होगी। यदि वे इसके लिए अनुमति नहीं देते तो सभी विरासत कोड को फिर से लिखना होगा। मैंने एक उत्तर लिखा है जो इस टिप्पणी पर विस्तृत है।
डेविड हैमेन

35

यह उत्तर के लिए एक उत्तर और विस्तारित टिप्पणी दोनों है , यह 1999 से कानूनी सी नहीं है। कोई भी सभ्य आधुनिक सी संकलक इसके लिए अनुमति नहीं देता है।

हां, auto a=1;C1999 में अवैध है (और C2011 भी)। सिर्फ इसलिए कि यह अब अवैध है इसका मतलब यह नहीं है कि एक आधुनिक सी कंपाइलर को कोड को अस्वीकार करना चाहिए जिसमें ऐसे निर्माण शामिल हैं। मैं इसके ठीक विपरीत तर्क दूंगा कि एक सभ्य आधुनिक सी कंपाइलर को अभी भी इसके लिए अनुमति देनी चाहिए।

क्लैंग और जीसीसी दोनों ही ऐसा करते हैं जब मानक के 1999 या 2011 संस्करणों के खिलाफ प्रश्न में नमूना कोड का संकलन करते हैं। दोनों कंपाइलर एक डायग्नोस्टिक जारी करते हैं और फिर ले जाते हैं जैसे कि आपत्तिजनक बयान दिया गया था auto int a=1;

मेरी राय में, यह वही है जो एक सभ्य संकलक को करना चाहिए। एक नैदानिक ​​जारी करके, क्लैंग और जीसीसी मानक के साथ पूर्ण अनुरूप हैं। मानक यह नहीं कहता है कि एक संकलक को अवैध कोड को अस्वीकार करना चाहिए। मानक केवल यह कहता है कि यदि एक अनुवाद इकाई में किसी वाक्यविन्यास नियम या बाधा (5.1.1.3) का उल्लंघन होता है, तो एक अनुरूप कार्यान्वयन को कम से कम एक नैदानिक ​​संदेश का उत्पादन करना चाहिए।

दिए गए कोड में अवैध निर्माण शामिल हैं, कोई भी सभ्य संकलक अवैध कोड की समझ बनाने की कोशिश करेगा ताकि संकलक कोड में अगली त्रुटि पा सके। एक कंपाइलर जो पहली त्रुटि पर रुकता है वह बहुत अच्छा कंपाइलर नहीं है। समझ से बाहर करने का एक तरीका है auto a=1, जो "निहित int" नियम को लागू करना है। यह नियम कंपाइलर को auto a=1यह व्याख्या करने के लिए मजबूर करता है जैसे कि auto int a=1जब कंपाइलर C90 या K & R मोड में उपयोग किया जाता है।

अधिकांश कंपाइलर आमतौर पर कोड को अस्वीकार करते हैं (अस्वीकार करते हैं: एक वस्तु फ़ाइल या एक निष्पादन योग्य बनाने से इनकार करते हैं) जिसमें अवैध सिंटैक्स होता है। यह एक ऐसा मामला है जहां संकलक लेखकों ने फैसला किया कि संकलन करने में विफल होना सबसे अच्छा विकल्प नहीं है। सबसे अच्छी बात यह है कि डायग्नोस्टिक जारी करना, कोड को ठीक करना, और जारी रखना। वहाँ बस बहुत विरासत कोड है कि इस तरह के निर्माण के साथ peppered है register a=1;। संकलक उस कोड को C99 या C11 मोड में (नैदानिक ​​के साथ, निश्चित रूप से) संकलित करने में सक्षम होना चाहिए।


1
@ लार्समैन - मैं देख सकता हूँ कि आप कहाँ से आ रहे हैं। आप एक -ffs-please-stop-allowing-constructs-from-some-previous-millenniumसंकलक विकल्प, या अधिक रसीला, एक -fstrict-complianceविकल्प चाहते हैं। संकलक पर बड़बड़ाते हुए: "जब मैंने -std = c11 का उपयोग किया तो मुझे उम्मीद नहीं थी कि प्राचीन K & R kruft संकलन करने के लिए। वास्तव में, मैं चाहता था कि यह संकलन न हो !"
डेविड हैमेन

1
असल में नहीं, मैं चालू करने के लिए करना चाहते हैं पर संकलन करने के लिए सबसे खराब cruft पाने के लिए एक झंडा। लेकिन -std=c99सख्त होना सही दिशा में एक कदम होगा :)
फ्रेड फू

1
यदि आप उपयोग करते हैं gcc -g -O3 -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Werror(जो कि मैं नियमित रूप से उपयोग करता हूं, यहां तक ​​कि एसओ पर प्रश्नों से कोड पर भी), तो आप जो चाहते हैं, उसके काफी करीब पहुंच जाते हैं। मैं GCC को कम से कम -std=c99और अधिमानतः डिफ़ॉल्ट रूप से -std=c11(या -std=gnu11; वे अधिक संभावना है कि ऐसा करते हैं) चाहेंगे, लेकिन तब तक, ... आप उन विकल्पों को ट्वीक कर सकते हैं; -pedantic, -Wshadow, -Wold-style-declarationऔर कुछ अन्य उपयोगी हो सकता है, लेकिन यह एक अच्छा विकल्प के सेट शुरू कर रहा है।
जोनाथन लेफ़लर

3
@David Hammen: न तो चक्रीय जटिलता, परियोजना प्रबंधक, न ही कंपनी की नीतियां भाषा के तत्व हैं।
जेरी बी

3
जीसीसी में आप जो व्यवहार चाहते हैं, उसे पाने के लिए झंडा है-pedantic-errors
'

29

auto2011 मानक से पहले Cऔर बाद में एक अर्थ है C++। इसका मतलब है कि एक चर में स्वचालित जीवनकाल है, अर्थात, जीवनकाल गुंजाइश द्वारा निर्धारित किया गया है । यह, जैसे, staticजीवनकाल, जहां एक चर "हमेशा" रहता है, की गुंजाइश की परवाह किए बिना विरोध किया जाता है । autoडिफ़ॉल्ट जीवनकाल है, और लगभग स्पष्ट रूप से वर्तनी नहीं है। यही कारण है कि इसमें अर्थ बदलना सुरक्षित था C++

अब C99 मानक से पहले, यदि आप एक चर के प्रकार को निर्दिष्ट नहीं करते हैं, तो यह चूक करता है int

तो auto a = 1;आप के साथ (और परिभाषित) एक intचर घोषित कर रहे हैं , जीवन भर गुंजाइश द्वारा निर्धारित किया जाता है।

("जीवनकाल" को और अधिक ठीक से "भंडारण अवधि" कहा जाता है, लेकिन मुझे लगता है कि शायद कम स्पष्ट है)।


ठीक है, इसलिए वास्तव में ऑटो ए = 1 को सी में अनुमति दी गई है और इसका मतलब है कि स्वचालित भंडारण अवधि के साथ एक अंतर चर।
lee77

1
उचित रूप से, "संग्रहण अवधि" मानों की एक सूची लेता है, "स्वचालित", "स्थिर", "गतिशील", "थ्रेड"। "लाइफटाइम" वस्तु के जीवन का वास्तविक समय है। तो चर में भंडारण अवधि "स्वचालित" और जीवनकाल " mainफ़ंक्शन के दायरे की अवधि " है।
स्टीव जेसोप

@Steve हाँ, मुझे लगता है कि यह सूचित करते हैं मतलब नहीं था autoऔर staticकेवल दो संभावनाएं हैं। मैं अपने उत्तर को पूछने वाले पर लक्षित तरीके से लिखने की कोशिश कर रहा था, जो C++(और C) के लिए बहुत नया लगता है , इसलिए मैंने विवरणों पर थोड़ा ध्यान दिया। शायद यह एक बुरा विचार था; उन्हें जल्द या बाद में कवर करने की आवश्यकता है।
BoBTFish

1
@BoBTFish: ओह, मुझे उस बारे में शिकायत नहीं थी। मेरा तात्पर्य "आजीवन", जो कि एक अवधि है, और "संग्रहण अवधि" के बीच के शब्दार्थ अंतर पर विस्तार करने का है, जिसे अधिक सटीक रूप से "संग्रहण अवधि श्रेणी" कहा जा सकता है।
स्टीव जेसोप

यह निहित intसामान 1999 से C से हटा दिया गया है।
जेन्स गुस्तेद

8

C, और C ++ की ऐतिहासिक बोलियों में, autoएक कीवर्ड अर्थ है जिसका aस्वचालित भंडारण होता है। चूंकि यह केवल स्थानीय चर पर लागू किया जा सकता है, जो डिफ़ॉल्ट रूप से स्वचालित हैं, कोई भी इसका उपयोग नहीं करता है; जिसके कारण C ++ ने अब कीवर्ड को फिर से तैयार कर लिया है।

ऐतिहासिक रूप से, C ने बिना किसी प्रकार के विशेष के साथ परिवर्तनीय घोषणाओं की अनुमति दी है; प्रकार चूक करता है int। तो यह घोषणा के बराबर है

int a=1;

मुझे लगता है कि यह आधुनिक सी में पदावनत (और संभवतः निषिद्ध) है; लेकिन कुछ लोकप्रिय संकलक C90 के लिए डिफ़ॉल्ट होते हैं (जो, मुझे लगता है, इसकी अनुमति देता है), और, नाराजगी से, केवल चेतावनी को सक्षम करें यदि आप विशेष रूप से उनके लिए पूछें। जीसीसी के साथ संकलन और किसी के साथ C99 निर्दिष्ट करने -std=c99के लिए, या के साथ चेतावनी को सक्षम करने -Wallया -Wimplicit-intएक चेतावनी देता है:

warning: type defaults to int in declaration of a

4
यह 1999 के बाद से सी में वास्तव में निषिद्ध है।
जेन्स गुस्टेड

5

C में, autoइसका मतलब वही registerहै जो C ++ 11 में है: इसका मतलब है कि एक चर में स्वचालित भंडारण अवधि है।

और C99 से पहले C में (और Microsoft का संकलक C99 या C11 का समर्थन नहीं करता है, हालाँकि यह इसके कुछ हिस्सों का समर्थन कर सकता है), प्रकार को कई मामलों में छोड़ा जा सकता है, जहाँ यह डिफ़ॉल्ट होगा int

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


1
क्या C ++ 11 में रजिस्टर किया गया कीवर्ड नहीं है?
sordid

@sordid हाँ, यह है। C ++ 11 से पहले, autoऔर registerइसका ठीक वही अर्थ था (मैंने पहले टिप्पणी की थी कि register-क्वालिफ़ाइड वैरिएबल का पता लेने पर प्रतिबंध था, लेकिन यह C ++ के लिए गलत था)। register, जबकि पदावनत, अभी के लिए अपने पुराने अर्थ को बरकरार रखता है।

5
@JensGustedt: उत्तर यह नहीं कहता कि वे हैं। यह कहता है कि autoC का मतलब registerC ++ के समान है , जो यह करता है (दोनों का अर्थ है स्वचालित भंडारण अवधि, और कुछ नहीं)।
माइक सेमुर

3

दृश्य स्टूडियो संकलन प्रकार पर उपलब्ध है right click on file -> Properties -> C/C++ -> Advanced -> Compile As। यह सुनिश्चित करने के लिए कि इसे C बल /TCविकल्प के रूप में संकलित किया गया है । इस मामले में यह वही है जो लार्समैन ने कहा था (पुराने सी autoकीवर्ड)। यह आपके जानने के बिना C ++ के रूप में संकलित किया जा सकता है।


3

एक भंडारण वर्ग सी कार्यक्रम के दायरे (और दृश्यता) और चर और / या कार्यों के जीवन काल को परिभाषित करता है।

निम्नलिखित भंडारण कक्षाएं हैं जो सी प्रोग्राम में उपयोग की जा सकती हैं

auto
register
static
extern

auto सभी स्थानीय चर के लिए डिफ़ॉल्ट भंडारण वर्ग है।

{
        int Count;
        auto int Month;
}

ऊपर दिया गया उदाहरण एक ही भंडारण वर्ग के साथ दो चर को परिभाषित करता है। ऑटो का उपयोग केवल फ़ंक्शंस यानी स्थानीय चर में किया जा सकता है।

intautoनीचे कोड के लिए डिफ़ॉल्ट प्रकार है :

auto Month;
/* Equals to */
int Month;

नीचे कोड कानूनी है:

/* Default-int */
main()
{
    reurn 0;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.