GCC 7.3 - 3.10.4. Duplication of Side Effects

3.10.4 साइड इफेक्ट्स का दोहराव




gcc

3.10.4 साइड इफेक्ट्स का दोहराव

कई सी कार्यक्रम "न्यूनतम" के लिए एक स्थूल मंत्री को परिभाषित करते हैं, जैसे:

#define min(X, Y)  ((X) < (Y) ? (X) : (Y))

जब आप इस मैक्रो का उपयोग साइड इफेक्ट वाले तर्क के साथ करते हैं, जैसा कि यहां दिखाया गया है,

next = min (x + y, foo (z));

यह इस प्रकार है:

next = ((x + y) < (foo (z)) ? (x + y) : (foo (z)));

जहां x + y को X और Y लिए foo (z) को प्रतिस्थापित किया गया है।

फ़ंक्शन foo का उपयोग केवल एक बार कथन में किया जाता है जैसा कि कार्यक्रम में दिखाई देता है, लेकिन अभिव्यक्ति foo (z) को मैक्रो विस्तार में दो बार प्रतिस्थापित किया गया है। परिणामस्वरूप, स्टेटमेंट निष्पादित होने पर दो बार foo को कॉल किया जा सकता है। यदि इसके साइड इफेक्ट्स हैं या यदि यह गणना करने में लंबा समय लेता है, तो परिणाम वही नहीं हो सकते हैं जो आप चाहते थे। हम कहते हैं कि min असुरक्षित मैक्रो है।

इस समस्या का सबसे अच्छा समाधान यह है कि min को केवल एक बार foo (z) के मान की गणना करने वाले तरीके से परिभाषित करें। C भाषा इसे करने के लिए कोई मानक तरीका प्रदान नहीं करती है, लेकिन इसे GNU एक्सटेंशन के साथ निम्न प्रकार से किया जा सकता है:

#define min(X, Y)                \
({ typeof (X) x_ = (X);          \
   typeof (Y) y_ = (Y);          \
   (x_ < y_) ? x_ : y_; })

' ({...}) ' संकेतन एक यौगिक कथन का उत्पादन करता है जो एक अभिव्यक्ति के रूप में कार्य करता है। इसका मूल्य इसके अंतिम कथन का मूल्य है। यह हमें स्थानीय चर को परिभाषित करने और प्रत्येक तर्क को एक को असाइन करने की अनुमति देता है। व्यापक दायरे के पहचानकर्ता के साथ संघर्ष के जोखिम को कम करने के लिए उनके नाम के बाद स्थानीय चर अंडरस्कोर होते हैं (यह पूरी तरह से बचना असंभव है)। अब प्रत्येक तर्क का मूल्यांकन एक बार किया जाता है।

यदि आप जीएनयू सी एक्सटेंशन का उपयोग नहीं करना चाहते हैं, तो मैक्रो min का उपयोग करते समय एकमात्र समाधान सावधान रहना है। उदाहरण के लिए, आप foo (z) के मूल्य की गणना कर सकते हैं, इसे एक चर में बचा सकते हैं, और उस चर का उपयोग min :

#define min(X, Y)  ((X) < (Y) ? (X) : (Y))
…
{
  int tem = foo (z);
  next = min (x + y, tem);
}

(जहां हम मानते हैं कि foo रिटर्न int )।

अगला: सेल्फ-रेफ़रेंशियल मैक्रोज़ , पिछला: सेमीकोलन को निगलते हुए , ऊपर: मैक्रो नुकसान [ Contents ] [ Index ]