C में नीचे दिए गए कथनों में से कौन सा प्रयोग करना बेहतर है?
static const int var = 5;
या
#define var 5
या
enum { var = 5 };
C में नीचे दिए गए कथनों में से कौन सा प्रयोग करना बेहतर है?
static const int var = 5;
या
#define var 5
या
enum { var = 5 };
जवाबों:
यह इस बात पर निर्भर करता है कि आपको किस मूल्य की आवश्यकता है। आपने (अब तक और सभी ने) तीसरा विकल्प छोड़ दिया:
static const int var = 5;#define var 5enum { var = 5 };नाम की पसंद के बारे में मुद्दों की अनदेखी, फिर:
इसलिए, अधिकांश संदर्भों में, विकल्पों पर 'एनम' को प्राथमिकता दें। अन्यथा, पहली और आखिरी बुलेट पॉइंट्स को नियंत्रित करने वाले कारक होने की संभावना है - और अगर आपको दोनों को एक साथ संतुष्ट करने की आवश्यकता है, तो आपको कठिन सोचना होगा।
यदि आप C ++ के बारे में पूछ रहे थे, तो आप विकल्प (1) - स्टेटिक कास्ट - हर बार उपयोग करेंगे।
enumहै कि वे int([C99] 6.7.2.2/3) के रूप में कार्यान्वित किए जाते हैं । एक #defineआपको अहस्ताक्षरित और लंबे Uऔर Lप्रत्यय के साथ निर्दिष्ट करता है , और constआपको एक प्रकार देता है। enumसामान्य प्रकार के रूपांतरणों के कारण समस्याएँ हो सकती हैं।
enumऔर न ही #defineअतिरिक्त जगह का उपयोग करता है, प्रति से। मान ऑब्जेक्ट कोड में डेटा खंड या हीप या स्टैक पर संग्रहीत किए जाने के बजाय निर्देशों के भाग के रूप में दिखाई देगा। आपके पास कुछ स्थान आवंटित होगा static const int, लेकिन यदि आप कोई पता नहीं लगाते हैं तो कंपाइलर इसे अनुकूलित कर सकता है।
enumS (और static const) के लिए एक और 'वोट' : उन्हें बदला नहीं जा सकता। a 'd defineहो सकता है #undefine, जहाँ a enumऔर static constदिए गए मान पर नियत हैं।
आम तौर पर बोलना:
static const
क्योंकि यह गुंजाइश का सम्मान करता है और टाइप-सेफ है।
केवल वही चेतावनी जो मैं देख सकता था: यदि आप चाहते हैं कि चर को संभवतः कमांड लाइन पर परिभाषित किया जाए। अभी भी एक विकल्प है:
#ifdef VAR // Very bad name, not long enough, too general, etc..
static int const var = VAR;
#else
static int const var = 5; // default value
#endif
जब भी संभव हो, मैक्रोज़ / एलिप्सिस के बजाय, एक प्रकार-सुरक्षित विकल्प का उपयोग करें।
यदि आप वास्तव में एक मैक्रो के साथ जाने के लिए आवश्यक हैं (उदाहरण के लिए, आप चाहते हैं __FILE__या __LINE__), तो आप अपने मैक्रो को बहुत सावधानी से नाम देंगे: इसके नामकरण सम्मेलन में बूस्ट परियोजना के नाम से शुरू होने वाले सभी ऊपरी मामलों की सिफारिश करता है (यहां BOOST_ ), पुस्तकालय से इनकार करते समय आप यह देखेंगे (आम तौर पर) विशेष क्षेत्र (पुस्तकालय) के नाम के बाद और फिर सार्थक नाम के साथ।
यह आम तौर पर लंबे नामों के लिए बनाता है :)
staticजिनका पता लिया जाता है, उन्हें बने रहना चाहिए; और यदि पता लिया जाता है तो एक #defineया enum(कोई पता नहीं) का उपयोग नहीं किया जा सकता है ... इसलिए मैं वास्तव में यह देखने में विफल हूं कि क्या विकल्प का उपयोग किया जा सकता था। यदि आप "संकलन समय मूल्यांकन" के साथ दूर कर सकते हैं, तो आप extern constइसके बजाय देख सकते हैं ।
#ifअधिक बेहतर हो सकता है #ifdefबूलियन झंडे के लिए है, लेकिन इस मामले में यह यह असंभव को परिभाषित करने बनाना होगा varके रूप में 0कमांड लाइन से। तो इस मामले में, #ifdefअधिक समझ में आता है, जब तक के 0लिए एक कानूनी मूल्य है var।
सी में, विशेष रूप से? C में सही उत्तर है: उपयोग #define(या, यदि उपयुक्त हो, enum)
हालांकि const, किसी वस्तु की टेढ़ी-मेढ़ी और टाइपिंग संपत्तियों का होना फायदेमंद है, जबकि constC में वास्तविकता में ऑब्जेक्ट्स (C ++ के विपरीत) सही स्थिरांक नहीं हैं और इसलिए आमतौर पर अधिकांश व्यावहारिक मामलों में बेकार होते हैं।
इसलिए, सी में चुनाव द्वारा निर्धारित किया जाना चाहिए कि आप अपने निरंतर उपयोग की योजना कैसे बनाते हैं। उदाहरण के लिए, आप किसी const intऑब्जेक्ट को caseलेबल के रूप में उपयोग नहीं कर सकते (जबकि मैक्रो काम करेगा)। आप किसी const intवस्तु को बिट-फील्ड चौड़ाई (जबकि मैक्रो काम करेंगे) के रूप में उपयोग नहीं कर सकते । C89 / 90 में आप constसरणी आकार निर्दिष्ट करने के लिए किसी ऑब्जेक्ट का उपयोग नहीं कर सकते (जबकि मैक्रो काम करेगा)। यहां तक कि C99 में आप किसी constऑब्जेक्ट का उपयोग उस सरणी आकार को निर्दिष्ट करने के लिए नहीं कर सकते हैं जब आपको गैर- वीएलए सरणी की आवश्यकता होती है।
यदि यह आपके लिए महत्वपूर्ण है तो यह आपकी पसंद का निर्धारण करेगा। ज्यादातर समय, आपके पास #defineसी में उपयोग करने के अलावा कोई विकल्प नहीं होगा और दूसरे विकल्प को न भूलें, जो कि सी में सही स्थिरांक पैदा करता है enum।
C ++ में constऑब्जेक्ट सही स्थिरांक होते हैं, इसलिए C ++ में constवेरिएंट को प्राथमिकता देना लगभग हमेशा बेहतर होता है ( staticC ++ में स्पष्ट की कोई आवश्यकता नहीं )।
const intकेस-लेबल में वस्तुओं का उपयोग करना सी भाषा के सभी संस्करणों में अवैध है। (बेशक, आपका कंपाइलर एक गैर-मानक C ++ के रूप में समर्थन करने के लिए स्वतंत्र है - भाषा विस्तार की तरह।)
constकेवल पढ़ने का मतलब है। const int r = rand();पूरी तरह से कानूनी है।
constexprतुलना में उपयोग करना बेहतर है । conststlarraybitset
switch()कथन में परीक्षण करना होगा , caseएक में नहीं । मैंने अभी-अभी इस पर पकड़ लिया है got
के बीच का अंतर static constऔर #defineहै कि पूर्व का उपयोग करता है स्मृति और बाद में भंडारण के लिए स्मृति का उपयोग नहीं करता है। दूसरे, आप किसी पते का पास नहीं कर सकते, #defineजबकि आप किसी के पते को पास नहीं कर सकते static const। वास्तव में यह इस बात पर निर्भर करता है कि हम किस परिस्थिति में हैं, हमें इन दोनों में से किसी एक का चयन करना होगा। दोनों अलग-अलग परिस्थितियों में अपने सर्वश्रेष्ठ में हैं। कृपया यह न समझें कि एक दूसरे से बेहतर है ... :-)
अगर ऐसा होता, तो डेनिस रिची ने अकेले सबसे अच्छा रखा होता ... हाहाहा ... :-)
constस्मृति का उपयोग करता है। GCC (4.5.3 और कुछ नए संस्करणों के साथ परीक्षण) const int-O3 का उपयोग करते समय आसानी से आपके कोड में एक प्रत्यक्ष शाब्दिक में अनुकूलन करता है । इसलिए यदि आप कम रैम एंबेडेड डेवलपमेंट (जैसे AVR) करते हैं तो यदि आप GCC या किसी अन्य संगत कंपाइलर का उपयोग करते हैं तो आप सुरक्षित रूप से C का उपयोग कर सकते हैं। मैंने इसका परीक्षण नहीं किया है, लेकिन क्लैंग से यही बात करने की उम्मीद है कि बी.डब्ल्यू.टी.
सी #defineमें अधिक लोकप्रिय है। आप उदाहरण के लिए सरणी आकार घोषित करने के लिए उन मूल्यों का उपयोग कर सकते हैं:
#define MAXLEN 5
void foo(void) {
int bar[MAXLEN];
}
एएनएसआई सी आपको static constइस संदर्भ में एस का उपयोग करने की अनुमति नहीं देता है जहां तक मुझे पता है। C ++ में आपको इन मामलों में मैक्रोज़ से बचना चाहिए। तुम लिख सकते हो
const int maxlen = 5;
void foo() {
int bar[maxlen];
}
और यहां तक कि बाहर छोड़ दें staticक्योंकि आंतरिक संबंध constपहले से ही [सी ++ में] द्वारा निहित है ।
const int MY_CONSTANT = 5;एक फ़ाइल में हो सकता है और इसे extern const int MY_CONSTANT;दूसरे में एक्सेस कर सकता हूं । मैं constडिफ़ॉल्ट व्यवहार को बदलने के बारे में मानक (C99 कम से कम) में कोई जानकारी नहीं पा सका "6.2.2: 5 यदि किसी वस्तु के लिए एक पहचान for एर की घोषणा में and ले गुंजाइश है और कोई भंडारण-वर्ग की युक्ति, एर नहीं है, तो इसका लिंकेज बाहरी है"।
barएक वीएलए (चर लंबाई सरणी) है; संकलक कोड उत्पन्न करने की संभावना है जैसे कि इसकी लंबाई स्थिर थी।
constC का एक और दोष यह है कि आप दूसरे को इनिशियलाइज़ करने में मूल्य का उपयोग नहीं कर सकते हैं const।
static int const NUMBER_OF_FINGERS_PER_HAND = 5;
static int const NUMBER_OF_HANDS = 2;
// initializer element is not constant, this does not work.
static int const NUMBER_OF_FINGERS = NUMBER_OF_FINGERS_PER_HAND
* NUMBER_OF_HANDS;
यहां तक कि यह एक कास्ट के साथ काम नहीं करता है क्योंकि कंपाइलर इसे एक स्थिर के रूप में नहीं देखता है:
static uint8_t const ARRAY_SIZE = 16;
static int8_t const lookup_table[ARRAY_SIZE] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; // ARRAY_SIZE not a constant!
मुझे constइन मामलों में टाइप करने में खुशी होगी , अन्यथा ...
static uint8_t const ARRAY_SIZE = 16;अचानक नहीं संकलन अब थोड़ा चुनौतीपूर्ण हो सकता है, खासकर जब #define ARRAY_SIZE 256हेडर के पेचीदा वेब में गहरी दस परतों को दफन किया जाता है। कि सभी कैप नाम ARRAY_SIZEपरेशानी के लिए पूछ रहे हैं। मैक्रोज़ के लिए ALL_CAPS आरक्षित करें, और ALL_CAPS फॉर्म में नहीं होने वाले मैक्रो को कभी भी परिभाषित न करें।
const। यह और अधिक उत्कीर्ण किया जा सकता है!
अगर आप इससे दूर हो सकते हैं, तो static constइसके कई फायदे हैं। यह सामान्य स्कोप सिद्धांतों का पालन करता है, डिबगर में दिखाई देता है, और आमतौर पर उन नियमों का पालन करता है जो चर मानते हैं।
हालांकि, कम से कम मूल सी मानक में, यह वास्तव में एक स्थिर नहीं है। यदि आप उपयोग करते हैं #define var 5, तो आप int foo[var];एक घोषणा के रूप में लिख सकते हैं , लेकिन आप ऐसा नहीं कर सकते (सिवाय इसके एक संकलक विस्तार के रूप में) static const int var = 5;यह C ++ में ऐसा नहीं है, जहां static constसंस्करण का उपयोग #defineसंस्करण कहीं भी किया जा सकता है, और मुझे विश्वास है कि C99 के मामले में भी यही है।
हालांकि, #defineलोअरकेस नाम के साथ एक स्थिरांक का नाम कभी न रखें । यह अनुवाद इकाई के अंत तक उस नाम के किसी भी संभावित उपयोग को ओवरराइड करेगा। मैक्रो स्थिरांक में होना चाहिए जो प्रभावी रूप से अपने स्वयं के नामस्थान है, जो परंपरागत रूप से सभी पूंजी पत्र हैं, शायद एक उपसर्ग के साथ।
constC99 में अभी भी वास्तविक स्थिरांक नहीं है। आप constC99 में ए के साथ ऐरे आकार की घोषणा कर सकते हैं , लेकिन केवल इसलिए कि C99 वेरिएबल लेंथ एरे का समर्थन करता है। इस कारण से, यह केवल वही काम करेगा जहां वीएलएएएस की अनुमति है। उदाहरण के लिए, C99 में भी, आप अभी भी consta में सदस्य सरणी के आकार को घोषित करने के लिए उपयोग नहीं कर सकते हैं struct।
const intआकार के साथ आरंभ करने देगा जैसे कि यह C ++ कास्ट या मैक्रो था। क्या आप मानक से GCC के इस विचलन पर निर्भर होना चाहते हैं, निश्चित रूप से आपकी पसंद है, मैं व्यक्तिगत रूप से इसके साथ जाऊंगा जब तक कि आप वास्तव में GCC या Clang की तुलना में किसी अन्य संकलक का उपयोग नहीं कर सकते, बाद में यहाँ एक ही सुविधा है (Clang के साथ परीक्षण) 3.7)।
यह हमेशा #define के बजाय कास्ट का उपयोग करने के लिए बेहतर है। ऐसा इसलिए है क्योंकि कांसेप्ट को कंपाइलर और # डेफिन द्वारा प्रीप्रोसेसर द्वारा इलाज किया जाता है। यह ऐसा है जैसे #define खुद कोड (मोटे तौर पर बोलने) का हिस्सा नहीं है।
उदाहरण:
#define PI 3.1416
प्रतीकात्मक नाम पीआई को संकलक द्वारा कभी नहीं देखा जा सकता है; प्रीप्रोसेसर द्वारा इसे हटाया जा सकता है इससे पहले कि स्रोत कोड किसी कंपाइलर के पास पहुंच जाए। परिणामस्वरूप, PI नाम प्रतीक तालिका में दर्ज नहीं हो सकता है। यदि आप निरंतरता के उपयोग को शामिल करते हुए संकलन के दौरान एक त्रुटि प्राप्त करते हैं, तो यह भ्रामक हो सकता है, क्योंकि त्रुटि संदेश 3.1416 को संदर्भित कर सकता है, पीआई को नहीं। यदि PI को एक हेडर फ़ाइल में परिभाषित किया गया है जिसे आपने नहीं लिखा है, तो आपको पता नहीं चलेगा कि 3.1416 कहां से आया है।
यह समस्या एक प्रतीकात्मक डिबगर में भी फसल कर सकती है, क्योंकि, फिर से, आप जिस नाम से प्रोग्रामिंग कर रहे हैं वह प्रतीक तालिका में नहीं हो सकता है।
समाधान:
const double PI = 3.1416; //or static const...
#define var 5अगर आपको चीजें पसंद हैं तो आप परेशानी का कारण बनेंगे mystruct.var।
उदाहरण के लिए,
struct mystruct {
int var;
};
#define var 5
int main() {
struct mystruct foo;
foo.var = 1;
return 0;
}
प्रीप्रोसेसर इसकी जगह लेगा और कोड संकलित नहीं करेगा। इस कारण से, पारंपरिक कोडिंग शैली का सुझाव है कि #defineसंघर्ष से बचने के लिए सभी निरंतर एस बड़े अक्षरों का उपयोग करते हैं।
मैंने एक अंतर प्रदर्शित करने के लिए त्वरित परीक्षण कार्यक्रम लिखा:
#include <stdio.h>
enum {ENUM_DEFINED=16};
enum {ENUM_DEFINED=32};
#define DEFINED_DEFINED 16
#define DEFINED_DEFINED 32
int main(int argc, char *argv[]) {
printf("%d, %d\n", DEFINED_DEFINED, ENUM_DEFINED);
return(0);
}
यह इन त्रुटियों और चेतावनियों के साथ संकलित है:
main.c:6:7: error: redefinition of enumerator 'ENUM_DEFINED'
enum {ENUM_DEFINED=32};
^
main.c:5:7: note: previous definition is here
enum {ENUM_DEFINED=16};
^
main.c:9:9: warning: 'DEFINED_DEFINED' macro redefined [-Wmacro-redefined]
#define DEFINED_DEFINED 32
^
main.c:8:9: note: previous definition is here
#define DEFINED_DEFINED 16
^
ध्यान दें कि एनम एक त्रुटि देता है जब परिभाषित एक चेतावनी देता है।
परिभाषा
const int const_value = 5;
हमेशा एक निरंतर मान को परिभाषित नहीं करता है। कुछ संकलक (उदाहरण के लिए 0.9.26 tcc ) सिर्फ "const_value" नाम से पहचानी गई स्मृति को आवंटित करते हैं। पहचानकर्ता "const_value" का उपयोग करके आप इस मेमोरी को संशोधित नहीं कर सकते। लेकिन आप फिर भी एक अन्य पहचानकर्ता का उपयोग करके मेमोरी को संशोधित कर सकते हैं:
const int const_value = 5;
int *mutable_value = (int*) &const_value;
*mutable_value = 3;
printf("%i", const_value); // The output may be 5 or 3, depending on the compiler.
इसका मतलब परिभाषा है
#define CONST_VALUE 5
एक निरंतर मूल्य को परिभाषित करने का एकमात्र तरीका है जिसे किसी भी तरह से संशोधित नहीं किया जा सकता है।
#defineतो मशीन कोड को संपादित करके भी संशोधित किया जा सकता है।
5। लेकिन कोई संशोधित नहीं कर सकता #defineक्योंकि यह प्रीप्रोसेसर मैक्रो है। यह बाइनरी प्रोग्राम में मौजूद नहीं है। यदि कोई उन सभी स्थानों को संशोधित करना चाहता CONST_VALUEथा, जहां एक का उपयोग किया जाता था, तो उसे एक-एक करके करना पड़ता था।
#define CONST 5, फिर if (CONST == 5) { do_this(); } else { do_that(); }, और संकलक elseशाखा को समाप्त कर देता है । CONST6 में बदलने के लिए आप मशीन कोड को कैसे संपादित करने का प्रस्ताव रखते हैं ?
#defineयह बुलेट-प्रूफ नहीं है।
#define। स्रोत कोड और recompile को संपादित करने का एकमात्र वास्तविक तरीका यही है।
हालाँकि यह सवाल पूर्णांक के बारे में था, यह ध्यान देने योग्य है कि #define और enums बेकार हैं यदि आपको एक स्थिर संरचना या स्ट्रिंग की आवश्यकता है। ये दोनों आमतौर पर संकेत के रूप में कार्य करने के लिए पारित किए जाते हैं। (स्ट्रिंग्स के साथ इसकी आवश्यकता है; संरचनाओं के साथ यह अधिक कुशल है।)
पूर्णांक के लिए के रूप में, यदि आप बहुत सीमित स्मृति के साथ एक एम्बेडेड वातावरण में हैं, तो आपको इस बारे में चिंता करने की आवश्यकता हो सकती है कि निरंतर कहाँ संग्रहीत है और इसे कैसे एक्सेस किया जाता है। कंपाइलर रन समय में दो कॉन्स्ट्स जोड़ सकता है, लेकिन कंपाइल टाइम में दो #Dfines जोड़ें। एक #define स्थिरांक को एक या एक से अधिक MOV [तत्काल] निर्देशों में परिवर्तित किया जा सकता है, जिसका अर्थ है कि स्थिरांक प्रोग्राम मेमोरी में प्रभावी रूप से संग्रहीत है। डेटा मेमोरी में एक कॉन्स्टेंट कॉन्स्टेंट को .const सेक्शन में स्टोर किया जाएगा। हार्वर्ड वास्तुकला के साथ सिस्टम में, प्रदर्शन और स्मृति उपयोग में अंतर हो सकते हैं, हालांकि वे संभवतः छोटे होंगे। वे आंतरिक छोरों के हार्ड-कोर अनुकूलन के लिए मायने रख सकते हैं।
मत सोचो कि "जो हमेशा सबसे अच्छा होता है" के लिए एक उत्तर है, लेकिन, जैसा कि मैथ्यू ने कहा
static const
सुरक्षित है #defineहालाँकि, मेरे सबसे बड़े पालतू जानवर के दृश्य स्टूडियो में डिबगिंग करते समय आप चर नहीं देख सकते हैं। यह एक त्रुटि देता है कि प्रतीक नहीं पाया जा सकता है।
संयोग से, एक विकल्प #define, जो उचित ढलान प्रदान करता है, लेकिन "वास्तविक" स्थिर की तरह व्यवहार करता है, "एनम" है। उदाहरण के लिए:
enum {number_ten = 10;}
कई मामलों में, एन्यूमरेटेड प्रकारों को परिभाषित करना और उन प्रकारों के चर बनाना उपयोगी है; यदि ऐसा किया जाता है, तो डिबगर अपने गणना नाम के अनुसार चर प्रदर्शित करने में सक्षम हो सकते हैं।
हालांकि ऐसा करने के साथ एक महत्वपूर्ण चेतावनी: सी ++ में, एन्यूमरेटेड प्रकार के पूर्णांक के साथ सीमित संगतता है। उदाहरण के लिए, डिफ़ॉल्ट रूप से, कोई उन पर अंकगणित नहीं कर सकता है। मुझे लगता है कि एनम के लिए एक जिज्ञासु डिफ़ॉल्ट व्यवहार होना चाहिए; हालांकि "सख्त एनम" प्रकार का होना अच्छा होता, सी + + आमतौर पर सी के साथ संगत होने की इच्छा को देखते हुए, मुझे लगता है कि "एनम" प्रकार का डिफ़ॉल्ट व्यवहार पूर्णांकों के साथ विनिमेय होना चाहिए।
int, इसलिए "एनम हैक" का उपयोग अन्य पूर्णांक प्रकारों के साथ नहीं किया जा सकता है। (गणना प्रकार कुछ कार्यान्वयन-परिभाषित पूर्णांक प्रकार के साथ संगत है, जरूरी नहीं int, लेकिन इस मामले में वह प्रकार गुमनाम है जो कोई फर्क नहीं पड़ता।)
intएक एन्यूमरेशन-टाइप किए गए वैरिएबल (जो कंपाइलर को करने की अनुमति देता है) के अलावा कोई अन्य टाइप करता है और कोई इस तरह के वैरिएबल को असाइन करने की कोशिश करता है अपने स्वयं के गणन का सदस्य। काश मानक समितियाँ निर्दिष्ट शब्दार्थ के साथ पूर्णांक प्रकारों की घोषणा के पोर्टेबल तरीके जोड़ देतीं। किसी भी मंच, charआकार की परवाह किए बिना , एक प्रकार की घोषणा करने में सक्षम होना चाहिए जो मॉड 65536 को लपेट देगा, भले ही कंपाइलर को बहुत सारे AND R0,#0xFFFFया समकक्ष निर्देश जोड़ना हो ।
uint16_t, हालांकि यह एक गणन प्रकार नहीं है। उपयोगकर्ता को दिए गए एन्यूमरेशन प्रकार का प्रतिनिधित्व करने के लिए उपयोग किए जाने वाले पूर्णांक प्रकार को निर्दिष्ट करने के लिए अच्छा होगा, लेकिन आप व्यक्तिगत मूल्यों के typedefलिए uint16_tऔर उसी के साथ श्रृंखला की एक ही प्रभाव को प्राप्त कर सकते #defineहैं।
2U < -1Lसही और दूसरों के रूप में गलत का मूल्यांकन करेंगे, और अब हम इस तथ्य के साथ फंस गए हैं कि कुछ प्लेटफॉर्म एक तुलना uint32_tऔर int32_tहस्ताक्षर किए गए के बीच लागू करेंगे और कुछ के रूप में अहस्ताक्षरित, लेकिन इसका मतलब यह नहीं है कि समिति सी को एक ऊर्ध्व-संगत उत्तराधिकारी को परिभाषित नहीं कर सकती है जिसमें ऐसे प्रकार शामिल हैं जिनके शब्दार्थ सभी संकलक पर संगत होंगे।
एक साधारण अंतर:
पूर्व-प्रसंस्करण समय में, निरंतर को इसके मूल्य के साथ बदल दिया जाता है। इसलिए आप डिरेफेरेंस ऑपरेटर को डिफाइन नहीं कर सकते, लेकिन आप डीरेफेरेंस ऑपरेटर को वैरिएबल पर लागू कर सकते हैं।
जैसा कि आप मान लेंगे, परिभाषित है कि स्थिर गति है।
उदाहरण के लिए, होना:
#define mymax 100
आप नहीं कर सकते printf("address of constant is %p",&mymax);।
लेकिन होने
const int mymax_var=100
आप कर सकते हैं printf("address of constant is %p",&mymax_var);।
अधिक स्पष्ट होने के लिए, परिभाषित को पूर्व-प्रसंस्करण चरण में इसके मूल्य से बदल दिया जाता है, इसलिए हमारे पास कार्यक्रम में कोई चर संग्रहीत नहीं है। हमारे पास प्रोग्राम के टेक्स्ट सेगमेंट से सिर्फ कोड है जहां परिभाषित किया गया था।
हालांकि, स्थैतिक कास्ट के लिए हमारे पास एक चर है जो कहीं आवंटित किया गया है। Gcc के लिए, स्थैतिक कास्ट को प्रोग्राम के टेक्स्ट सेगमेंट में आवंटित किया जाता है।
ऊपर, मैं संदर्भ ऑपरेटर के बारे में बताना चाहता था ताकि संदर्भ को संदर्भ से बदल दें।
constक्वालिफायर के लिए बहुत अलग शब्दार्थ हैं । सी में एनम-कॉन्स्टेंट के अलावा सिम्बिका स्थिरांक नहीं हैं । A const intपरिवर्तनशील है। आप भाषा और विशिष्ट कार्यान्वयन को भी भ्रमित करते हैं। वस्तु को रखने की कोई आवश्यकता नहीं है। और यह gcc के लिए भी सही नहीं है: आम तौर पर यह अनुभाग constमें योग्य चर रखता है .rodata। लेकिन यह लक्ष्य प्लेटफॉर्म पर निर्भर करता है। और आपका मतलब है ऑपरेटर का पता &।
हमने MBF16X पर उत्पादित कोडांतरक कोड को देखा ... दोनों वेरिएंट अंकगणित संचालन (उदाहरण के लिए ADD तत्काल) के लिए एक ही कोड में परिणाम करते हैं।
तो पुरानी शैली है, const intजबकि प्रकार की जाँच के लिए पसंद किया #defineजाता है। शायद यह संकलक-विशिष्ट है। तो अपने उत्पादित कोडांतरक कोड की जाँच करें।
मुझे यकीन नहीं है कि अगर मैं सही हूं, लेकिन मेरी राय में #defineडी मूल्य कॉलिंग किसी भी अन्य सामान्य रूप से घोषित चर (या कास्ट वैल्यू) को कॉल करने की तुलना में बहुत तेज है। ऐसा इसलिए है क्योंकि जब प्रोग्राम चल रहा है और इसे कुछ सामान्य रूप से घोषित चर का उपयोग करने की आवश्यकता है, तो उस चर को प्राप्त करने के लिए स्मृति में सटीक स्थान पर कूदने की आवश्यकता है।
इसके विपरीत जब यह #defined मान का उपयोग करता है , तो प्रोग्राम को किसी भी आवंटित मेमोरी में कूदने की आवश्यकता नहीं है, यह सिर्फ मूल्य लेता है। यदि #define myValue 7और प्रोग्राम कॉलिंग myValue, यह ठीक वैसा ही व्यवहार करता है जैसे कि जब यह कॉल करता है 7।