2010-05-10 14 views
37

एंड्रॉयड ओपन-सोर्स qemu कोड मैं कोड के इस रेखा के पार भाग गया में:क्यों आप "सही" हालत के लिए एक मूल्य बताए त्रिगुट ऑपरेटर का प्रयोग करेंगे (एक्स = एक्स: 1)

machine->max_cpus = machine->max_cpus ?: 1; /* Default to UP */ 

यह सिर्फ कहने का एक भ्रामक तरीका है:

if (machine->max_cpus) { 
    ; //do nothing 
} else { 
machine->max_cpus = 1; 
} 

यदि हां, तो यह नहीं होगा स्पष्ट रूप:

if (machine->max_cpus == 0) machine->max_cpus = 1; 

दिलचस्प है, इस संकलित करता है तथा जीसीसी के साथ ठीक काम करता है, लेकिन http://www.comeaucomputing.com/tryitout/ पर संकलित नहीं करता है।

+5

रुको, क्या ?! ... यह मेरे लिए एक बग की तरह दिखता है। –

+0

@ कोनराड - शायद नहीं। टिप्पणी से पता चलता है कि रेखा डिफ़ॉल्ट सेट करती है - यदि "max_cpus सेट नहीं है, तो डिफ़ॉल्ट मान सेट करें"। – Mac

+0

यदि यह कानूनी है, तो मैं इससे बचूंगा क्योंकि ऐसा लगता है कि यह एक बग हो सकता है। यहां हम इसके बारे में एक बड़ी चर्चा कर रहे हैं, यह साबित करते हुए कि अगर यह कथन का उपयोग करने के लिए स्पष्ट होगा। –

उत्तर

48

इस के साथ एक सशर्त अभिव्यक्ति में ऑपरेंड

बीच संकार्य लोप छोड़ा जा सकता है सी

5,7 सशर्त, करने के लिए एक अस्पष्ट विस्तार के रूप में जीएनयू में permitted है। फिर यदि पहला ऑपरेंड nonzero है, तो इसका मान सशर्त अभिव्यक्ति का मान है।

इसलिए, अभिव्यक्ति

x ? : y 

कि अगर अशून्य है x का मान है; अन्यथा, वाई का मूल्य।

यह उदाहरण पूरी तरह से

इस सरल मामले में
x ? x : y 

के बराबर है, करने की क्षमता को छोड़ बीच संकार्य विशेष रूप से उपयोगी नहीं है। जब यह बन जाता है तब उपयोगी होता है जब पहला ऑपरेंड करता है, या (यदि यह एक मैक्रो तर्क है), में साइड इफेक्ट होता है। फिर दोहराएं मध्य में ऑपरेंड साइड इफेक्ट दो बार करेगा। मध्य ऑपरेंड को छोड़कर मान का उपयोग पहले से ही के बिना गणना के अवांछित प्रभावों के साथ किया जाता है।

जैसा कि आप शायद अनुमान लगा सकते हैं, इसे टालने योग्यता और पोर्टेबिलिटी कारणों के लिए अनुशंसा की जाती है। मैं ईमानदारी से इस तरह के व्याकरण-असंगत विस्तार को देखकर आश्चर्यचकित हूं।

+4

दिलचस्प। यह एक वाक्य रचनात्मक विशेषता के रूप में अविश्वसनीय रूप से उपयोगी लगता है, और समझने के लिए अविश्वसनीय रूप से अस्पष्ट है। –

+0

मैं सहमत हूं। लेकिन कई चीजें हैं जो इसे अधिक सुरुचिपूर्ण बनाने के लिए सी में जोड़ सकती हैं, मुझे आश्चर्य है कि एक कंपाइलर विक्रेता स्पष्ट रूप से सी व्याकरण में ऐसे अनुमोदित परिवर्तन करेगा। यदि यह सी ++ था, तो यह एक और कहानी है क्योंकि यह असंगतता का जंगल था। – Uri

+13

अरे, इस तरह '||' काम करना चाहिए। – Potatoswatter

1

के & आर बीएनएफ दिखाता है कि "?" के बीच एक अभिव्यक्ति की आवश्यकता है तथा ":"। मुझे नहीं लगता कि जीसीसी को निदान के बिना संकलित किया जाना चाहिए।

+2

यह मेरा मानना ​​है कि एक गैर-मानक जीसीसी एक्सटेंशन है। सबसे अच्छा बचा है। –

10

यह एक GCC extension मतलब यह है कि "अगर हालत सही है, इसका इस्तेमाल, और यह अन्य मान का उपयोग" है, इसलिए

machine->max_cpus = machine->max_cpus ?: 1; 

के लिए

machine->max_cpus = machine->max_cpus ? machine->max_cpus : 1; 

आशुलिपि है हालांकि अगर सशर्त है साइड इफेक्ट्स, यह केवल

3

पर चलाया जाएगा यह GCC extension है, और स्थिति के दुष्प्रभाव होने पर यह अधिक दिलचस्प और उपयोगी हो जाता है।

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

6

जीसीसी के -pedantic ध्वज का उपयोग करना, यह कहना

foo.c करता है? अभिव्यक्ति

0

एक और उपयोगी है इसके लिए मामला - एक फ़ंक्शन या विधि को कॉल करते समय मध्यवर्ती चर का उन्मूलन जो शून्य लौटा सकता है, कि हम दो बार कॉल करने से बचना चाहते हैं। उदाहरण के लिए (उद्देश्य-सी), मान लीजिए कि अगर हम मौजूद हैं तो हम किसी फ़ाइल को सरणी में अनपैक करना चाहते हैं, अन्यथा खाली सरणी लौटाएं।

- (NSArray*)hydrateBacklogFromFile:(NSString *path) 
{ 
    NSArray *backlog = @[]; 
    NSData *backlogData = [NSData dataWithContentsOfFile:path]; 
    if (backlogData) 
    { 
     backlog = [NSKeyedUnarchiver unarchiveObjectWithData:backlogData] ?: backlog; 
    } 
    return backlog; 
} 

विकल्प कम संक्षिप्त हैं।

- (NSArray*)hydrateBacklogFromFile:(NSString *path) 
{ 
    NSArray *backlog = @[]; 
    NSData *backlogData = [NSData dataWithContentsOfFile:path]; 
    if (backlogData) 
    { 
     NSArray *tempArray = [NSKeyedUnarchiver unarchiveObjectWithData:backlogData]; 
     if (tempArray != nil) 
     { 
      backlog = tempArray; 
     } 
    } 
    return backlog; 
} 

या साथ भद्दा कई रिटर्न आदि

- (NSArray*)hydrateBacklogFromFile:(NSString *path) 
{ 
    NSData *backlogData = [NSData dataWithContentsOfFile:path]; 
    if (backlogData) 
    { 
     NSArray *tempArray = [NSKeyedUnarchiver unarchiveObjectWithData:backlogData]; 
     if (tempArray != nil) 
     { 
      return tempArray; 
     } 
    } 
    return @[]; 
} 

तो यह उपयोगी वाक्यात्मक चीनी कि मैं काफी पठनीय खोजने के लिए है। डाउनसाइड्स

  • एक पॉइंटर को एक बूल में लागू रूपांतरण। यह एक लंबे समय से सी सम्मेलन है, लेकिन अधिकांश आधुनिक भाषाएं इसे अस्वीकार करती हैं, किसी भी पोर्टिंग प्रयासों को जटिल बनाती हैं।

  • जैसा कि अन्य ने कहा है कि यह एक गैर-मानक विस्तार भी है, इसलिए से बचा जाना चाहिए यदि पोर्टेबिलिटी बिल्कुल विचार कर रही हो।

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