सी की छिपी विशेषताएं


141

मुझे पता है कि सभी सी संकलक कार्यान्वयन के पीछे एक मानक है, इसलिए कोई छिपी हुई विशेषताएं नहीं होनी चाहिए। इसके बावजूद, मुझे यकीन है कि सभी सी डेवलपर्स के पास छिपी / गुप्त चालें हैं जो वे हर समय उपयोग करते हैं।


यह बहुत अच्छा होगा यदि आप / कोई व्यक्ति इस प्रश्न के C # और पर्ल संस्करणों में सबसे अच्छी छुपी हुई विशेषताओं को चुनने के लिए "प्रश्न" संपादित करें।
डोनल फेलो

जवाबों:


62

कार्य बिंदु। आप फंक्शन पॉइंटर्स टेबल का उपयोग लागू करने के लिए कर सकते हैं, उदाहरण के लिए, फास्ट इनडायरेक्ट-थ्रेडेड कोड इंटरप्रिटर्स (FORTH) या बाइट-कोड डिस्पैचर्स, या OO- जैसे वर्चुअल तरीकों का अनुकरण करने के लिए।

फिर मानक पुस्तकालय में छिपे हुए रत्न होते हैं, जैसे कि क्यूसोर्ट (), बीएसओआरसी (), स्ट्रैप्रबक (), स्ट्रैस्पन () [बाद के दो स्ट्रेटोक () प्रतिस्थापन को लागू करने के लिए उपयोगी होते हैं।

सी की एक मिसफिट यह है कि हस्ताक्षरित अंकगणित अतिप्रवाह अपरिभाषित व्यवहार (यूबी) है। इसलिए जब भी आप एक्स + वाई जैसे कोई अभिव्यक्ति देखते हैं, तो दोनों पर हस्ताक्षर किए जा रहे हैं, यह संभावित रूप से अतिप्रवाह और यूबी का कारण बन सकता है।


29
लेकिन अगर वे अतिप्रवाह पर निर्दिष्ट व्यवहार करते थे, तो यह वास्तुशिल्प पर बहुत धीमी गति से होता था जहां यह सामान्य व्यवहार नहीं था। बहुत कम रनटाइम ओवरहेड हमेशा सी का डिज़ाइन लक्ष्य रहा है, और इसका मतलब है कि इस तरह की बहुत सी चीजें अपरिभाषित हैं।
मार्क बेकर

9
मैं बहुत अच्छी तरह से वाकिफ हूं कि ओवरफ्लो यूबी क्यों है। यह अभी भी एक मिसफिट है, क्योंकि मानक में कम से कम लाइब्रेरी रूटीन होना चाहिए जो अंकगणित अतिप्रवाह (सभी बुनियादी संचालन के) w / o के लिए परीक्षण कर सके, जो UB का कारण बनता है।
२०:०५ पर zvrba

2
@zvrba, "लाइब्रेरी रूटीन जो अंकगणितीय अतिप्रवाह (सभी मूल संचालन के लिए) का परीक्षण कर सकते हैं" यदि आपने इसे जोड़ा था, तो आपको किसी भी पूर्णांक अंकगणितीय संचालन के लिए महत्वपूर्ण प्रदर्शन हिट की आवश्यकता होगी। ===== केस स्टडी मतलाब विशेष रूप से रैपिंग या संतृप्त करने के लिए पूर्णांक अतिप्रवाह व्यवहार को नियंत्रित करने की सुविधा को जोड़ता है। और जब भी अतिप्रवाह होता है तो यह एक अपवाद फेंकता है ==> मैटलैब पूर्णांक परिचालनों का प्रदर्शन: बहुत कम। मेरा अपना निष्कर्ष: मुझे लगता है कि मतलाब एक सम्मोहक केस स्टडी है जो दिखाता है कि आप पूर्णांक ओवरफ़्लो जाँच क्यों नहीं चाहते हैं।
ट्रेवर बॉयड स्मिथ

15
मैंने कहा कि मानक को अंकगणितीय अतिप्रवाह की जाँच के लिए पुस्तकालय सहायता प्रदान करनी चाहिए थी । अब, यदि आप कभी भी इसका उपयोग नहीं करते हैं, तो एक लाइब्रेरी रूटीन एक प्रदर्शन को कैसे प्रभावित कर सकता है?
१०:५२ पर जुवरा

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

116

GCC संकलक की एक चाल के अधिक, लेकिन आप संकलक के लिए शाखा संकेत दे सकते हैं (लिनक्स केनन में आम)

#define likely(x)       __builtin_expect((x),1)
#define unlikely(x)     __builtin_expect((x),0)

देखें: http://kerneltrap.org/node/4705

इसके बारे में मुझे जो पसंद है वह यह है कि यह कुछ कार्यों के लिए कुछ अभिव्यक्तियाँ भी जोड़ता है।

void foo(int arg)
{
     if (unlikely(arg == 0)) {
           do_this();
           return;
     }
     do_that();
     ...
}

2
यह चाल अच्छी है ... :) विशेष रूप से मैक्रोज़ के साथ आप परिभाषित करते हैं। :)
सूंदर -

77
int8_t
int16_t
int32_t
uint8_t
uint16_t
uint32_t

ये मानक में एक वैकल्पिक आइटम हैं, लेकिन यह एक छिपी हुई विशेषता होनी चाहिए, क्योंकि लोग लगातार उन्हें फिर से परिभाषित कर रहे हैं। एक कोड आधार जो मैंने काम किया है (और अभी भी करते हैं, अभी के लिए) में कई पुनर्मूल्यांकन हैं, सभी अलग-अलग पहचानकर्ताओं के साथ हैं। अधिकांश समय यह प्रीप्रोसेसर मैक्रोज़ के साथ होता है:

#define INT16 short
#define INT32  long

और इसी तरह। यह मुझे अपने बालों को बाहर निकालना चाहता है। बस मानक मानक पूर्णांक टाइपिंग का उपयोग करें!


3
मुझे लगता है कि वे C99 या तो हैं। मुझे यह सुनिश्चित करने के लिए एक पोर्टेबल तरीका नहीं मिला है।
एकुप्पी

3
वे C99 का एक वैकल्पिक हिस्सा हैं, लेकिन मुझे कोई भी कंपाइलर विक्रेताओं का पता नहीं है जो इसे लागू नहीं करते हैं।
बेन कॉलिन्स

10
stdint.h C99 में वैकल्पिक नहीं है, लेकिन C99 मानक का स्पष्ट रूप से अनुसरण करना कुछ विक्रेताओं ( खांसी Microsoft) के लिए है।
बेन कॉम्बे ऑक्ट

5
@Pete, यदि आप गुदा बनना चाहते हैं: (1) इस धागे ने Microsoft के किसी उत्पाद के साथ कोई लेना-देना नहीं किया है। (२) इस धागे का कभी भी C ++ से कोई लेना-देना नहीं था। (३) C ++ 97 जैसी कोई चीज नहीं है।
बेन कॉलिंस

5
Azillionmonkeys.com/qed/pstdint.h पर एक नज़र डालें - एक नज़दीकी पोर्टेबल stdint.h
gnud

73

अल्पविराम ऑपरेटर का व्यापक रूप से उपयोग नहीं किया जाता है। यह निश्चित रूप से दुरुपयोग किया जा सकता है, लेकिन यह बहुत उपयोगी भी हो सकता है। यह प्रयोग सबसे आम है:

for (int i=0; i<10; i++, doSomethingElse())
{
  /* whatever */
}

लेकिन आप इस ऑपरेटर का उपयोग कहीं भी कर सकते हैं। का निरीक्षण करें:

int j = (printf("Assigning variable j\n"), getValueFromSomewhere());

प्रत्येक कथन का मूल्यांकन किया जाता है, लेकिन अभिव्यक्ति का मूल्य अंतिम कथन का मूल्यांकन किया जाएगा।


7
CI के 20 वर्षों में कभी नहीं देखा है कि!
मार्टिन बेकेट

11
C ++ में आप इसे ओवरलोड भी कर सकते हैं।
राउटर लेवेन्स

6
कर सकते हैं! = बेशक। इसे ओवरलोडिंग के साथ खतरा यह है कि बिल्ट में पहले से ही सब कुछ लागू होता है, जिसमें शून्य भी शामिल है, इसलिए उपलब्ध अधिभार की कमी के लिए संकलन करने में विफल नहीं होगा। यानी, प्रोग्रामर को बहुत रस्सी देता है।
हारून

लूप के अंदर का इंट सी के साथ काम नहीं करेगा: यह सी ++ इंप्रूवमेंट है। क्या "," उसी ऑपरेशन के लिए है (i = 0, j = 10; मैं <j; j--, i ++)?
एआईएफ

63

प्रारंभिक संरचना शून्य करने के लिए

struct mystruct a = {0};

यह सभी स्ट्रेक्चर तत्वों को शून्य कर देगा।


2
हालाँकि, यदि कोई हो, तो यह पैडिंग को शून्य नहीं करता है।
मिकेग

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

6
@Andrew: memset/ callocdo "all बाइट्स ज़ीरो" (अर्थात भौतिक शून्य), जो वास्तव में सभी प्रकारों के लिए परिभाषित नहीं है। उचित तार्किक शून्य मानों के साथ सब कुछ{ 0 } सूचित करने की गारंटी है । उदाहरण के लिए, पॉइंटर्स अपने उचित अशक्त मूल्यों को प्राप्त करने के लिए गुरुंटेड हैं, भले ही दिए गए प्लेटफ़ॉर्म पर नल-मान हो । 0xBAADFOOD
एनटी

1
@nvl: आप भौतिक शून्य प्राप्त करते हैं जब आप बस ऑब्जेक्ट द्वारा कब्जे वाली सभी मेमोरी को सभी बिट्स-शून्य स्थिति में सेट करते हैं। यह वही है जो memset( 0दूसरे तर्क के साथ) करता है। जब आप स्रोत कोड में ऑब्जेक्ट को इनिशियलाइज़ / असाइन (या ) करते हैं तो आपको लॉजिकल ज़ीरो मिलता है । ये दो प्रकार के शून्य आवश्यक रूप से एक ही परिणाम नहीं देते हैं। जैसा कि सूचक के साथ उदाहरण में। जब आप एक पॉइंटर पर करते हैं , तो आपको एक पॉइंटर मिलता है । लेकिन जब आप एक पॉइंटर को असाइन करते हैं , तो आपको अशक्त पॉइंटर मान मिलता है , जो भौतिक स्तर पर या कुछ और हो सकता है। 0{ 0 }memset0x000000xBAADF00D
एएनटी

3
@nvl: ठीक है, व्यवहार में अंतर अक्सर वैचारिक ही होता है। लेकिन सिद्धांत रूप में, लगभग किसी भी प्रकार का हो सकता है। उदाहरण के लिए, double। आमतौर पर इसे IEEE-754 मानक के अनुसार लागू किया जाता है, जिसमें तार्किक शून्य और भौतिक शून्य समान होते हैं। लेकिन IEEE-754 को भाषा की आवश्यकता नहीं है। तो यह हो सकता है कि जब आप double d = 0;(तार्किक शून्य) करते हैं, तो शारीरिक रूप से कब्जे वाली स्मृति में कुछ बिट dशून्य नहीं होंगे।
एएनटी

52

बहु-चरित्र स्थिरांक:

int x = 'ABCD';

यह सेट xकरने के लिए 0x41424344(या 0x44434241, वास्तुकला के आधार पर)।

EDIT: यह तकनीक पोर्टेबल नहीं है, खासकर यदि आप int को क्रमबद्ध करते हैं। हालाँकि, यह सेल्फ-डॉक्यूमेंटिंग एनम बनाने के लिए बेहद उपयोगी हो सकता है। जैसे

enum state {
    stopped = 'STOP',
    running = 'RUN!',
    waiting = 'WAIT',
};

यह बहुत आसान बना देता है यदि आप एक कच्ची मेमोरी डंप को देख रहे हैं और इसे देखने के लिए बिना किसी एनम का मान निर्धारित करने की आवश्यकता है।


मुझे पूरा यकीन है कि यह एक पोर्टेबल निर्माण नहीं है। बहु-चरित्र स्थिरांक बनाने का परिणाम कार्यान्वयन-परिभाषित है।
मार्क बेस्सी

8
"पोर्टेबल नहीं" टिप्पणियाँ पूरी तरह से याद आती हैं। यह सिर्फ INT_MAX का उपयोग करने के लिए एक कार्यक्रम की आलोचना करने जैसा है क्योंकि INT_MAX "पोर्टेबल नहीं है" :) यह सुविधा उतनी ही पोर्टेबल है जितनी इसे होना चाहिए। मल्टी-चर स्थिरांक एक अत्यंत उपयोगी विशेषता है जो अद्वितीय पूर्णांक आईडी बनाने के लिए पठनीय तरीका प्रदान करता है।
एनटी

1
@ क्रिस लुत्ज़ - मुझे पूरा यकीन है कि अनुगामी अल्पविराम K & R के लिए वापस जाता है। यह दूसरे संस्करण (1988) में वर्णित है।
फेरुशियो

1
@Ferruccio: आप एग्रीलेट इनलाइज़र सूचियों में अनुगामी अल्पविराम के बारे में सोच रहे होंगे। Enum घोषणाओं में अनुगामी अल्पविराम के लिए - यह एक हालिया जोड़, C99 है।
चींटी

3
आप 'HANG' या 'BSOD' :-)
JBRWilkinson

44

मैंने कभी भी बिट फ़ील्ड का उपयोग नहीं किया, लेकिन वे अल्ट्रा-लो-लेवल सामान के लिए शांत लगते हैं।

struct cat {
    unsigned int legs:3;  // 3 bits for legs (0-4 fit in 3 bits)
    unsigned int lives:4; // 4 bits for lives (0-9 fit in 4 bits)
    // ...
};

cat make_cat()
{
    cat kitty;
    kitty.legs = 4;
    kitty.lives = 9;
    return kitty;
}

इसका मतलब है कि sizeof(cat)जितना छोटा हो सकता है sizeof(char)


आरोन और लेपी द्वारा टिप्पणी को शामिल किया गया , धन्यवाद दोस्तों।


एम्बेडेड सिस्टम या निम्न स्तर के ड्राइवर कोड पर - स्ट्रक्चर और यूनियनों का संयोजन और भी दिलचस्प है। एक उदाहरण है जब आप एक एसडी कार्ड के रजिस्टरों को पार्स करना पसंद करते हैं, तो आप इसे संघ (1) का उपयोग करके पढ़ सकते हैं और इसे संघ (2) का उपयोग करके पढ़ सकते हैं जो बिटफिल्ड की एक संरचना है।
ComSubVie

5
बिटफ़िल्ड पोर्टेबल नहीं हैं - संकलक स्वतंत्र रूप से चुन सकता है कि क्या, आपके उदाहरण में, पैरों को सबसे महत्वपूर्ण 3 बिट्स, या कम से कम 3 महत्वपूर्ण बिट्स आवंटित किया जाएगा।
zvrba

3
Bitfields एक उदाहरण है जहां मानक कार्यान्वयन को इतनी स्वतंत्रता देते हैं कि वे कैसे लागू होते हैं, कि व्यवहार में, वे लगभग बेकार हैं। यदि आप परवाह करते हैं कि कितने बिट्स एक मूल्य लेता है, और यह कैसे संग्रहीत किया जाता है, तो आप बिटमास्क का उपयोग करके बेहतर हैं।
मार्क बेस्सी

26
बिटफ़िल्ड वास्तव में पोर्टेबल हैं जब तक आप उन्हें संरचना तत्वों के रूप में मानते हैं, और "पूर्णांक के टुकड़े" नहीं। आकार, स्थान नहीं, सीमित स्मृति के साथ एक एम्बेडेड सिस्टम में मायने रखता है, क्योंकि प्रत्येक बिट कीमती है ... लेकिन आज के अधिकांश कोडर इसे याद रखने के लिए बहुत छोटे हैं। :-)
एडम लिस

5
@ एडम: स्थान एक एम्बेडेड सिस्टम (या कहीं और) में अच्छी तरह से बात कर सकता है, यदि आप अपने बाइट के भीतर बिटफील्ड की स्थिति पर निर्भर हैं। मास्क का प्रयोग किसी भी अस्पष्टता को दूर करता है। इसी तरह यूनियनों के लिए।
स्टीव मेलनिकॉफ़

37

C का एक मानक है, लेकिन सभी C कंपाइलर पूरी तरह से कंप्लेंट नहीं हैं (मैंने अभी तक कोई कंप्लीट C99 कंपाइलर नहीं देखा है!)।

उन्होंने कहा, मेरे द्वारा पसंद की जाने वाली तरकीबें वे हैं जो प्लेटफार्मों के पार गैर-स्पष्ट और पोर्टेबल हैं क्योंकि वे सी सिमेंटिक पर भरोसा करते हैं। वे आम तौर पर मैक्रोज़ या बिट अंकगणित के बारे में हैं।

उदाहरण के लिए: एक अस्थायी चर का उपयोग किए बिना दो अहस्ताक्षरित पूर्णांक को स्वैप करना:

...
a ^= b ; b ^= a; a ^=b;
...

या "विस्तृत सी" जैसे परिमित राज्य मशीनों का प्रतिनिधित्व करने के लिए:

FSM {
  STATE(x) {
    ...
    NEXTSTATE(y);
  }

  STATE(y) {
    ...
    if (x == 0) 
      NEXTSTATE(y);
    else 
      NEXTSTATE(x);
  }
}

निम्नलिखित मैक्रो के साथ प्राप्त किया जा सकता है:

#define FSM
#define STATE(x)      s_##x :
#define NEXTSTATE(x)  goto s_##x

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


18
सी चाइनिंग का समर्थन करता है, इसलिए आप एक ^ = b ^ = a ^ = b कर सकते हैं;
ओ जे।

4
कड़ाई से बोलते हुए, राज्य उदाहरण प्रीप्रोसेसर का एक टिक है, और सी भाषा नहीं - बाद वाले के बिना पूर्व का उपयोग करना संभव है।
ग्रेग व्हिटफील्ड

15
OJ: वास्तव में आप जो सुझाव देते हैं वह अनुक्रम बिंदु नियमों के कारण अपरिभाषित व्यवहार है। यह अधिकांश कंपाइलरों पर काम कर सकता है, लेकिन सही या पोर्टेबल नहीं है।
इवान टेरान सेप 25'08

5
एक स्वतंत्र रजिस्टर के मामले में Xor स्वैप वास्तव में कम कुशल हो सकता है। कोई भी सभ्य अनुकूलक अस्थायी चर को एक रजिस्टर बना देगा। कार्यान्वयन के आधार पर (और समानांतरता समर्थन की आवश्यकता) स्वैप वास्तव में एक रजिस्टर (जो समान होगा) के बजाय वास्तविक मेमोरी का उपयोग कर सकता है।
पॉल डे व्रिज

27
कृपया वास्तव में कभी ऐसा न करें: en.wikipedia.org/wiki/…
क्रिश्चियन Oudard

37

गूंथने के उपकरण जैसी इंटरलाकिंग संरचनाएं :

strncpy(to, from, count)
char *to, *from;
int count;
{
    int n = (count + 7) / 8;
    switch (count % 8) {
    case 0: do { *to = *from++;
    case 7:      *to = *from++;
    case 6:      *to = *from++;
    case 5:      *to = *from++;
    case 4:      *to = *from++;
    case 3:      *to = *from++;
    case 2:      *to = *from++;
    case 1:      *to = *from++;
               } while (--n > 0);
    }
}

29
@ComSubVie, जो कोई भी डफ डिवाइस का उपयोग करता है वह एक स्क्रिप्ट किड है जिसने डफ डिवाइस को देखा और सोचा कि यदि वे डफ डिवाइस का उपयोग करते हैं तो उनका कोड 1337 दिखेगा। (१.) डफ का डिवाइस आधुनिक प्रोसेसर पर कोई प्रदर्शन नहीं बढ़ाता है क्योंकि आधुनिक प्रोसेसर में शून्य-ओवरहेड-लूपिंग है। दूसरे शब्दों में यह कोड का एक अप्रचलित टुकड़ा है। (२.) भले ही आपका प्रोसेसर शून्य-ओवरहेड-लूपिंग की पेशकश नहीं करता है, लेकिन इसमें शायद एसएसई / अल्टिवेक / वेक्टर-प्रोसेसिंग जैसी कोई चीज होगी जो आपके डफ के डिवाइस को शर्मिंदा कर देगी जब आप मेमसीपी () का उपयोग करते हैं। (३.) क्या मैंने उल्लेख किया है कि अन्य जो मेमसीपी कर रहे हैं () डफ उपयोगी नहीं है?
ट्रेवर बॉयड स्मिथ

2
@ComSubVie, कृपया मेरी मुट्ठी-मौत ( en.wikipedia.org/wiki/… ) से मिलें
ट्रेवर बॉयड स्मिथ

12
@Trevor: तो केवल स्क्रिप्ट kiddies प्रोग्राम 8051 और PIC माइक्रोकंट्रोलर, सही?
एसएफ।

6
@ ट्रेवर बॉयड स्मिथ: जबकि डफ का डिवाइस पुराना प्रतीत होता है, यह अभी भी एक ऐतिहासिक जिज्ञासा है, जो कॉमस्बवी के जवाब को मान्य करता है। वैसे भी, विकिपीडिया को उद्धृत करते हुए: "जब संस्करण 4.0 में डफ डिवाइस के कई उदाहरणों को XFree86 सर्वर से हटा दिया गया था, तो प्रदर्शन में उल्लेखनीय सुधार हुआ था।" ...
पीरसीबल

2
सिम्बियन पर, हमने एक बार फास्ट पिक्सेल कोडिंग के लिए विभिन्न छोरों का मूल्यांकन किया था; डफ का उपकरण, असेंबलर में, सबसे तेज था। तो यह अभी भी अपने स्मार्टफ़ोन पर मुख्य धारा एआरएम कोर पर प्रासंगिकता थी।
विल

33

मैं नामित शुरुआती के बहुत शौकीन हूं, C99 में जोड़ा गया है (और लंबे समय तक जीसीसी में समर्थित है):

#define FOO 16
#define BAR 3

myStructType_t myStuff[] = {
    [FOO] = { foo1, foo2, foo3 },
    [BAR] = { bar1, bar2, bar3 },
    ...

सरणी आरंभीकरण अब निर्भर स्थिति नहीं है। यदि आप FOO या BAR के मान बदलते हैं, तो सरणी आरंभीकरण स्वचालित रूप से उनके नए मूल्य के अनुरूप होगा।


सिंटैक्स gcc ने लंबे समय तक समर्थन किया है जो मानक C99 सिंटैक्स के समान नहीं है।
मार्क बेकर

28

C99 में कुछ भयानक कोई भी ऑर्डर संरचना आरंभीकरण है।

struct foo{
  int x;
  int y;
  char* name;
};

void main(){
  struct foo f = { .y = 23, .name = "awesome", .x = -38 };
}


27

अनाम संरचनाएं और सरणियाँ मेरी पसंदीदा हैं। (cf. http://www.run.montefiore.ulg.ac.be/~martin/resources/kung-fg.html )

setsockopt(yourSocket, SOL_SOCKET, SO_REUSEADDR, (int[]){1}, sizeof(int));

या

void myFunction(type* values) {
    while(*values) x=*values++;
}
myFunction((type[]){val1,val2,val3,val4,0});

यह भी जुड़ा हुआ सूची instanciate करने के लिए इस्तेमाल किया जा सकता है ...


3
इस सुविधा को आमतौर पर "यौगिक शाब्दिक" कहा जाता है। अनाम (या अनाम) संरचनाएँ नेस्टेड संरचनाएँ नामित करती हैं जिनका कोई सदस्य नाम नहीं है।
calandoa

मेरे GCC के अनुसार, "आईएसओ C90 यौगिक यौगिकों को मना करता है"।
jmtd

"आईएसओ C99 यौगिक शाब्दिक का समर्थन करता है।" "विस्तार के रूप में, GCC C89 मोड में और C ++ में यौगिक शाब्दिक समर्थन करता है" (dixit info gcc)। साथ ही, "जीएनयू विस्तार के रूप में, जीसीसी यौगिक शाब्दिकों द्वारा स्थिर भंडारण अवधि के साथ वस्तुओं के आरंभीकरण की अनुमति देता है (जो कि आईएसओ सी 99 में संभव नहीं है, क्योंकि आरम्भिक एक स्थिर नहीं है)।"
PypeBros

24

gcc में मेरे द्वारा आनंद ली जाने वाली C भाषा में कई एक्सटेंशन हैं, जो यहां मिल सकते हैं । मेरे पसंदीदा में से कुछ फ़ंक्शन विशेषताएँ हैं । एक अत्यंत उपयोगी उदाहरण स्वरूप विशेषता है। इसका उपयोग तब किया जा सकता है यदि आप एक कस्टम फ़ंक्शन को परिभाषित करते हैं जो प्रिंटफ प्रारूप स्ट्रिंग लेता है। यदि आप इस फ़ंक्शन विशेषता को सक्षम करते हैं, तो यह सुनिश्चित करने के लिए कि आपके प्रारूप स्ट्रिंग और तर्क मेल खाते हैं, gcc आपके तर्कों पर जाँच करेगा और उपयुक्त के रूप में चेतावनी या त्रुटियाँ उत्पन्न करेगा।

int my_printf (void *my_object, const char *my_format, ...)
            __attribute__ ((format (printf, 2, 3)));

24

(छिपी हुई) विशेषता है कि जब मैंने पहली बार देखा तो मुझे "झटका" लगा था। यह सुविधा आपको स्वरूपण निर्दिष्ट करने के लिए चर का उपयोग करने की अनुमति देती है। कोड के लिए देखो, आप बेहतर देखेंगे:

#include <stdio.h>

int main() {
    int a = 3;
    float b = 6.412355;
    printf("%.*f\n",a,b);
    return 0;
}

* चरित्र इस प्रभाव को प्राप्त करता है।


24

खैर ... मुझे लगता है कि सी भाषा के मजबूत बिंदुओं में से एक इसकी पोर्टेबिलिटी और मानकता है, इसलिए जब भी मैं वर्तमान में उपयोग कर रहा हूँ में कुछ "छिपी हुई चाल" पाता हूं, मैं इसका उपयोग नहीं करने की कोशिश करता हूं क्योंकि मैं इसे रखने की कोशिश करता हूं मानक और संभव के रूप में पोर्टेबल के रूप में सी कोड।


लेकिन वास्तव में, आपको कितनी बार अपने कोड को दूसरे संकलक के साथ संकलित करना होगा?
जो डी

3
@ जो डी अगर इसकी विंडोज / OSX / लिनक्स की तरह एक क्रॉस प्लेटफॉर्म प्रोजेक्ट है, तो शायद थोड़ा सा है, और x86 बनाम x86_64 और आदि जैसे अलग-अलग आर्क भी हैं ...
फिरौन

@JoeD जब तक आप एक बहुत संकरी परियोजना में नहीं होते हैं, जो एक कंपाइलर विक्रेता से शादी करके बहुत खुश होती है। आप वास्तव में संकलक स्विच करने से बचना चाह सकते हैं, लेकिन आप उस विकल्प को खुला रखना चाहते हैं। एम्बेडेड सिस्टम के साथ, आपको हमेशा एक विकल्प नहीं मिलता है, हालांकि। AHS, ASS।
एक्सटीएल


16

लगातार स्ट्रिंग का संघनन

मैं जवाबों में पहले से ही इसे देखकर बहुत हैरान था, क्योंकि सभी संकलक मुझे इसके समर्थन के बारे में जानते हैं, लेकिन कई प्रोग्रामर इसे अनदेखा करते दिखते हैं। कभी-कभी यह वास्तव में आसान होता है और न केवल मैक्रोज़ लिखते समय।

मेरे वर्तमान कोड में केस का उपयोग करें: मेरे पास #define PATH "/some/path/"एक कॉन्फ़िगरेशन फ़ाइल में है (वास्तव में यह मेकफाइल द्वारा तय किया गया है)। अब मैं फ़ाइलनाम सहित पूर्ण पथ का निर्माण करना चाहता हूं ताकि पुनर्मूल्यांकन खोला जा सके। यह बस जाता है:

fd = open(PATH "/file", flags);

के बजाय भयानक, लेकिन बहुत आम है:

char buffer[256];
snprintf(buffer, 256, "%s/file", PATH);
fd = open(buffer, flags);

ध्यान दें कि आम भयानक समाधान है:

  • जब तक तीन बार
  • पढ़ने में बहुत कम आसान
  • बहुत धीमा
  • इस पर कम शक्तिशाली एक अनियंत्रित बफर आकार सीमा के लिए निर्धारित है (लेकिन आपको निरंतर स्ट्रैस कॉन्टैक्शन के बिना बचने के लिए अधिक लंबे कोड का उपयोग करना होगा)।
  • अधिक स्टैक स्पेस का उपयोग करें

1
यह भी गंदा `का उपयोग किए बिना कई स्रोत लाइनों पर एक स्ट्रिंग निरंतर विभाजित करने के लिए उपयोगी है।
dolmen

15

खैर, मैंने कभी इसका इस्तेमाल नहीं किया है, और मुझे यकीन नहीं है कि क्या मैं कभी किसी को इसकी सलाह दूंगा, लेकिन मुझे लगता है कि यह प्रश्न साइमन तथम के सह-दिनचर्या चाल के उल्लेख के बिना अधूरा होगा


12

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

int x[] = { 1, 2, 3, };

enum foo { bar, baz, boom, };

ऐसा इसलिए किया गया ताकि यदि आप कोड स्वतः उत्पन्न कर रहे हैं तो आपको अंतिम अल्पविराम को समाप्त करने के बारे में चिंता करने की आवश्यकता नहीं है।


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

एनम C99 हो सकते हैं। Array initializers और अनुगामी अल्पविराम K & R हैं।
फेर्रूकियो

प्लेन एनम c89, AFAIK में थे। कम से कम वे उम्र भर रहे हैं।
एक्सटीएल

12

संरचना असाइनमेंट शांत है। बहुत से लोग महसूस नहीं करते हैं कि संरचनाएं भी मूल्य हैं, और उन्हें चारों ओर सौंपा जा सकता है, उपयोग करने की कोई आवश्यकता नहीं हैmemcpy() , जब एक साधारण असाइनमेंट चाल करता है, तो ।

उदाहरण के लिए, कुछ काल्पनिक 2D ग्राफिक्स लाइब्रेरी पर विचार करें, यह एक (पूर्णांक) स्क्रीन समन्वय का प्रतिनिधित्व करने के लिए एक प्रकार को परिभाषित कर सकता है:

typedef struct {
   int x;
   int y;
} Point;

अब, आप ऐसी चीजें करते हैं जो "गलत" लग सकती हैं, जैसे कि एक फ़ंक्शन लिखें जो फ़ंक्शन तर्कों से प्रारंभिक बिंदु बनाता है, और इसे वापस लौटाता है, जैसे:

Point point_new(int x, int y)
{
  Point p;
  p.x = x;
  p.y = y;
  return p;
}

यह तब तक सुरक्षित है, जब तक कि वापसी (मूल्य) संरचना असाइनमेंट का उपयोग करके मूल्य द्वारा कॉपी की जाती है:

Point origin;
origin = point_new(0, 0);

इस तरह आप बिल्कुल साफ-सुथरी और ऑब्जेक्ट-ओरिएंटेड-ईश कोड लिख सकते हैं, सभी सादे मानक सी में।


4
बेशक, इस तरह से गोल बड़ी संरचनाओं को पारित करने के लिए प्रदर्शन निहितार्थ हैं; यह अक्सर उपयोगी होता है (और वास्तव में कुछ ऐसा है जिसे बहुत से लोग महसूस नहीं करते हैं कि आप कर सकते हैं) लेकिन आपको यह विचार करने की आवश्यकता है कि क्या पासिंग पॉइंट बेहतर है।
मार्क बेकर

1
बेशक, वहाँ हो सकता है। Ít भी संकलक के लिए उपयोग का पता लगाने और इसे अनुकूलित करने के लिए काफी संभव है।
खोलना

अगर कोई भी तत्व इंगित करता है, तो सावधान रहें, क्योंकि आप बिंदुओं की नकल खुद करेंगे, उनकी सामग्री नहीं। बेशक, वही सच है अगर आप मेम्कपी () का उपयोग करते हैं।
एडम लिस

जब तक यह वैश्विक अनुकूलन नहीं कर सकता है तब तक संकलक इस रूपांतरित-दर-मान को बाईपास नहीं कर सकता है।
ब्लिसोरब्लेड

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

10

अजीब वेक्टर अनुक्रमण:

int v[100]; int index = 10; 
/* v[index] it's the same thing as index[v] */

4
यह और भी बेहतर है ... चार सी = 2 ["हैलो"]; (c == 'l' इसके बाद)।
yrp

5
इतना अजीब नहीं है जब आप उस v [इंडेक्स] == * (v + इंडेक्स) और इंडेक्स [v] == * (इंडेक्स + वी) पर विचार करते हैं
फेरुचियो

17
कृपया मुझे बताएं कि आप वास्तव में इस "हर समय" का उपयोग नहीं करते हैं, जैसे सवाल पूछता है!
20

9

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

सामान्य रूप से छिपी हुई सुविधाओं या भाषा की चालों को हतोत्साहित किया जाता है क्योंकि आप अपने कंपाइलर उपयोगों में से जो भी C मानक (रों) के रेजर किनारे पर चल रहे हैं। इस तरह के कई ट्रिक एक कंपाइलर से दूसरे में काम नहीं करते हैं, और अक्सर इस तरह के फीचर्स कंपाइलर सूट के एक वर्जन से दिए गए निर्माता के दूसरे वर्जन से फेल हो जाएंगे।

सी कोड को तोड़ने वाले विभिन्न ट्रिक में शामिल हैं:

  1. इस बात पर निर्भर करते हुए कि संकलक किस प्रकार स्मृति में संरचित करता है।
  2. धीरज धरने पर मान लियापूर्णांकों / फ़्लोट्स की ।
  3. समारोह पर अनुमान ABIs।
  4. उस दिशा पर मान्यताओं जो स्टैक फ्रेम बढ़ते हैं।
  5. बयानों के भीतर निष्पादन के आदेश के बारे में अनुमान।
  6. फ़ंक्शन तर्कों में बयानों के निष्पादन के आदेश के बारे में अनुमान।
  7. बिट आकार या छोटे, अंतर, लंबे, फ्लोट और दोहरे प्रकार की सटीकता पर अनुमान।

जब भी प्रोग्रामर निष्पादन मॉडल के बारे में धारणाएँ बनाते हैं, तो अन्य समस्याएं और समस्याएं उत्पन्न होती हैं, जो सभी सी मानकों में 'कंपाइलर निर्भर' व्यवहार के रूप में निर्दिष्ट होती हैं।


उनमें से अधिकांश को हल करने के लिए, उन मान्यताओं को अपने प्लेटफ़ॉर्म की विशेषताओं पर निर्भर करें, और प्रत्येक प्लेटफॉर्म का अपने हेडर में वर्णन करें। आदेश निष्पादन एक अपवाद है - उस पर कभी भरोसा न करें; अन्य विचारों पर, प्रत्येक मंच को एक विश्वसनीय निर्णय लेने की आवश्यकता होती है।
Blaisorblade

2
@ ब्लेज़रब्लड, और भी बेहतर, अपनी मान्यताओं को एक तरह से दस्तावेज करने के लिए संकलन-समय के दावे का उपयोग करें जो संकलन का एक मंच पर विफल कर देगा जहां उनका उल्लंघन किया जाता है।
RBerteig

मुझे लगता है कि किसी को दोनों को संयोजित करना चाहिए, ताकि आपका कोड कई प्लेटफार्मों पर काम करे (जो मूल उद्देश्य था), और यदि फीचर मैक्रोज़ गलत तरीके से सेट किए गए हैं, तो संकलन-समय के दावे इसे पकड़ लेंगे। मुझे यकीन नहीं है अगर, कहते हैं, फ़ंक्शन पर अनुमान ABIs संकलन-समय की पुष्टि के रूप में जांच योग्य हैं, लेकिन यह अन्य (वैध) वाले (निष्पादन के आदेश को छोड़कर;) के अधिकांश के लिए संभव होना चाहिए।
Blaisorblade

एबीआई चेक को एक परीक्षण सूट द्वारा नियंत्रित किया जाना चाहिए।
dolmen

9

Sscanf का उपयोग करते समय आप यह जानने के लिए% n का उपयोग कर सकते हैं कि आपको कहाँ पढ़ना जारी रखना चाहिए:

sscanf ( string, "%d%n", &number, &length );
string += length;

जाहिरा तौर पर, आप एक और उत्तर नहीं जोड़ सकते हैं, इसलिए मैं यहां एक दूसरे को शामिल करूंगा, आप "&&" और "" का उपयोग कर सकते हैं। सशर्त के रूप में:

#include <stdio.h>
#include <stdlib.h>

int main()
{
   1 || puts("Hello\n");
   0 || puts("Hi\n");
   1 && puts("ROFL\n");
   0 && puts("LOL\n");

   exit( 0 );
}

यह कोड आउटपुट करेगा:

नमस्ते
ROFL

8

कोड पर ब्रेक पॉइंट सेट करने के लिए INT (3) का उपयोग करना मेरा सर्वकालिक पसंदीदा है


3
मुझे नहीं लगता कि यह पोर्टेबल है। यह x86 पर काम करेगा, लेकिन अन्य प्लेटफार्मों के बारे में क्या?
क्रिस्टियन सियुपिटु

1
मेरे पास कोई विचार नहीं है - आपको इसके बारे में एक प्रश्न पोस्ट करना चाहिए
Dror Helper

2
यह एक अच्छी तकनीक है और यह X86 विशिष्ट है (हालांकि अन्य प्लेटफार्मों पर शायद ऐसी ही तकनीकें हैं)। हालांकि, यह सी की एक विशेषता नहीं है। यह गैर-मानक सी एक्सटेंशन या लाइब्रेरी कॉल पर निर्भर करता है।
फेर्रुकियो

1
GCC में __builtin_trap है और MSVC के लिए __debugbreak है जो किसी भी समर्थित आर्किटेक्चर पर काम करेगा।
एक्सल गेनिंग

8

सी की मेरी पसंदीदा "छिपी हुई" विशेषता, स्टैक पर वापस लिखने के लिए प्रिंट एन में% n का उपयोग है। आम तौर पर प्रिंटफ प्रारूप स्ट्रिंग के आधार पर स्टैक से पैरामीटर मानों को पॉप करता है, लेकिन% n उन्हें वापस लिख सकते हैं।

यहां 3.4.2 अनुभाग देखें । बहुत सारी कमजोरियों को जन्म दे सकता है।


लिंक अब काम नहीं कर रहा है, वास्तव में साइट को लगता है कि काम नहीं कर रहा है। क्या आप एक और लिंक प्रदान कर सकते हैं?
thequark

@ प्रश्न: "प्रारूप स्ट्रिंग कमजोरियों" के किसी भी लेख में इसकी कुछ जानकारी होगी .. (जैसे crypto.stanford.edu/cs155/papers/formatstring-1.2.pdf ) .. हालाँकि क्षेत्र की प्रकृति के कारण, सुरक्षा वेबसाइटें स्वयं थोड़ी परतदार हैं और वास्तविक अकादमिक लेखों को (कार्यान्वयन के साथ) कठिन है।
श्रीधर अय्यर

8

संकलक का उपयोग करते हुए संकलन-समय धारणा-जाँच: स्थिर उदाहरण, लेकिन संकलन-समय विन्यास योग्य स्थिरांक के साथ पुस्तकालयों के लिए वास्तव में उपयोगी हो सकता है।

#define D 1
#define DD 2

enum CompileTimeCheck
{
    MAKE_SURE_DD_IS_TWICE_D = 1/(2*(D) == (DD)),
    MAKE_SURE_DD_IS_POW2    = 1/((((DD) - 1) & (DD)) == 0)
};

2
+1 नीट। मैंने Microsoft से CompilerAssert मैक्रो का उपयोग किया था, लेकिन आपका भी बुरा नहीं है। ( #define CompilerAssert(exp) extern char _CompilerAssert[(exp)?1:-1])
पैट्रिक श्लुटर 12

1
मुझे एन्यूमरेशन मेथड पसंद है। डेड कोड एलिमिनेशन का फायदा उठाने से पहले मैंने जो तरीका इस्तेमाल किया, वह है: "if (bad_bad) {void BLORG_IS_WOOZLED (void); BLORG_IS_WOOZLED ();}"; जो लिंक समय तक नहीं हुआ, हालांकि इसने लाभ प्रदान करने का लाभ नहीं दिया; प्रोग्रामर को त्रुटि संदेश के माध्यम से पता है कि ब्लाग को मिटा दिया गया था।
सुपरकैट

8

Gcc (c) में कुछ मजेदार फीचर्स हैं जिन्हें आप सक्षम कर सकते हैं, जैसे नेस्टेड फंक्शन डिक्लेरेशन, और a ?: b का फॉर्म ?: ऑपरेटर, जो अगर a है तो गलत नहीं है।


8

मुझे हाल ही में 0 बिटफिल्ड की खोज हुई।

struct {
  int    a:3;
  int    b:2;
  int     :0;
  int    c:4;
  int    d:3;
};

जो एक लेआउट देगा

000aaabb 0ccccddd

इसके बजाय: 0;

0000aaab bccccddd

0 चौड़ाई क्षेत्र बताता है कि अगले परमाणु इकाई पर निम्नलिखित बिटफिल्ड सेट किए जाने चाहिए ( char)


7

C99- शैली चर तर्क मैक्रोज़, उर्फ

#define ERR(name, fmt, ...)   fprintf(stderr, "ERROR " #name ": " fmt "\n", \
                                  __VAR_ARGS__)

जिसका उपयोग किया जाएगा

ERR(errCantOpen, "File %s cannot be opened", filename);

यहां मैं स्ट्रिंगर ऑपरेटर और स्ट्रिंग निरंतर कॉन्सेटेशन का उपयोग करता हूं, अन्य विशेषताएं जो मुझे वास्तव में पसंद हैं।


आपके पास VA_ARGS में एक अतिरिक्त 'R' है ।
ब्लेसरब्लड

6

कुछ मामलों में परिवर्तनीय आकार के स्वचालित चर भी उपयोगी होते हैं। इन्हें i nC99 जोड़ा गया और लंबे समय तक gcc में समर्थित किया गया।

void foo(uint32_t extraPadding) {
    uint8_t commBuffer[sizeof(myProtocol_t) + extraPadding];

आप निश्चित आकार के प्रोटोकॉल शीर्षलेख और चर आकार डेटा के लिए कमरे के साथ स्टैक पर एक बफर के साथ समाप्त होते हैं। आप अल्लोका () के साथ समान प्रभाव प्राप्त कर सकते हैं, लेकिन यह सिंटैक्स अधिक कॉम्पैक्ट है।

आपको यह सुनिश्चित करना होगा कि इस रूटीन को कॉल करने से पहले एक्स्ट्रापैडिंग एक उचित मूल्य है, या आप स्टैक को उड़ाने का अंत करते हैं। आपको मॉलॉक या किसी अन्य मेमोरी आवंटन तकनीक को कॉल करने से पहले तर्कों की जांच करनी होगी, इसलिए यह वास्तव में असामान्य नहीं है।


क्या यह भी सही ढंग से काम करेगा अगर एक बाइट / चर लक्ष्य प्लेटफॉर्म पर 8 बिट्स चौड़ा नहीं है? मुझे पता है, वे मामले दुर्लभ हैं, लेकिन फिर भी ... :)
Stephan202
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.