C में #pragma का उपयोग


117

#pragmaउदाहरण के साथ, C के कुछ उपयोग क्या हैं ?


2
#pragmaनिर्देशन पूर्व-प्रसंस्करण अवस्था में जीवित रहता है। के विपरीत #includeऔर #define
smwikipedia


@smwikipedia आप का मतलब है कुछ व्यावहारिकता बची है? #pragma एक बार प्रीप्रोसेसर निर्देश है लेकिन #pragma पैक एक संकलक निर्देश है
लुईस केल्सी

जवाबों:


66

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

अधिक जानकारी के लिए देखें msdn


11
"सभी मशीनों और ऑपरेटिंग सिस्टम पर लागू हो सकता है या नहीं।" - और एक ही मशीन पर अलग-अलग कंपाइलर। और जिसका मतलब अलग-अलग कंपाइलरों पर अलग-अलग चीजें हो सकती हैं।
स्टीव जेसप

53

#pragma C के कार्यान्वयन-विशिष्ट करने के लिए उपयोग किया जाता है, अर्थात वैचारिक रूप से हठधर्मिता के बजाय वर्तमान संदर्भ के लिए व्यावहारिक होना चाहिए।

एक मैं नियमित रूप से उपयोग करता हूं, #pragma pack(1)जहां मैं एम्बेडेड समाधानों पर अपनी मेमोरी स्पेस से अधिक निचोड़ने की कोशिश कर रहा हूं, संरचनाओं के सरणियों के साथ जो अन्यथा 8 बाइट संरेखण के साथ समाप्त हो जाएंगे।

अफ़सोस कि हमारे पास #dogmaअभी तक नहीं है। वो मजेदार होगा ;)


@ShaneMacLaughlin, pragma(1)गति में भी सुधार नहीं करता है? देखें stackoverflow.com/questions/3318410/…
पचेरियर

4
@ स्पेसर, आमतौर पर नहीं। Jalfs टिप्पणियों के अनुसार, डेटा जो कि 4 बिट बाउंड्री पर 32 बिट प्रोसेसर या 8 बिट बाउंड्री के लिए 64 बिट प्रोसेसर के लिए संरेखित किया जाता है, आमतौर पर एक ही ऑपरेशन में लोड और संग्रहीत किया जाएगा। छोटी सीमाओं पर संरेखित डेटा लोड या स्टोर करने के लिए कई ऑपरेशन करेगा। यह धीमा है।
स्मैकएल

35

मैं आमतौर पर अगर संभव हो तो #pragmas के उपयोग से बचने की कोशिश करूंगा, क्योंकि वे बेहद संकलक और गैर-पोर्टेबल हैं। आप उन्हें एक पोर्टेबल फैशन में उपयोग करना चाहते हैं, तो आप एक साथ हर pragma घेर करना होगा #if/ #endifजोड़ी। जीसीसी प्रागमस के उपयोग को हतोत्साहित करता है, और वास्तव में उनमें से कुछ अन्य संकलक के साथ संगतता के लिए समर्थन करता है; जीसीसी के पास वही काम करने के अन्य तरीके हैं जिनके लिए अन्य कंपाइलर प्रैग्मस का उपयोग करते हैं।

उदाहरण के लिए, यहां बताया गया है कि आप यह सुनिश्चित करेंगे कि MSVC में एक संरचना कसकर पैक की गई हो (यानी सदस्यों के बीच कोई पैडिंग नहीं):

#pragma pack(push, 1)
struct PackedStructure
{
  char a;
  int b;
  short c;
};
#pragma pack(pop)
// sizeof(PackedStructure) == 7

यहाँ आप GCC में यही काम करेंगे:

struct PackedStructure __attribute__((__packed__))
{
  char a;
  int b;
  short c;
};
// sizeof(PackedStructure == 7)

जीसीसी कोड अधिक पोर्टेबल है, क्योंकि यदि आप यह संकलित करना चाहते हैं कि एक गैर-जीसीसी संकलक के साथ, आपको बस इतना करना है

#define __attribute__(x)

जबकि यदि आप MSVC कोड को पोर्ट करना चाहते हैं, तो आपको प्रत्येक प्राग #if/ a #endifजोड़ी के साथ घेरना होगा । सुंदर नहीं।


3
इसलिए यदि मैं MSVC पर GCC कोड संकलित करना चाहता हूं और संरचना को पैक करने की आवश्यकता है तो मैं वास्तव में इसे कैसे करूं?
स्मैकएल

2
जीसीसी के लिए, यह है struct __attribute__((__packed__)) PackedStructure
लॉरेंट डेब्रीकॉन

#pragma एक बार वास्तविक रूप से "संकलक निर्भर और गैर-पोर्टेबल" नहीं है। यह हर प्रमुख मंच और कई प्रमुख प्लेटफार्मों पर समर्थित है .. en.wikipedia.org/wiki/Pragma_once#Portability
xaxxon

1
ध्यान दें कि C99 और C11 दोनों में (C11) .66.10.6 प्रज्ञा निर्देश और Any1 कोई भी ऐसा प्रैग्म है जिसे कार्यान्वयन द्वारा मान्यता नहीं दी गई है। यहां तक ​​कि C90 का कहना है कि, हालांकि यह धारा .66.8.6 में था। (यह जीसीसी को गैर-अनुपालन योग्य बनाता है अगर यह hackतब चलता है जब यह एक ऐसे संघर्ष का सामना करता है जो इसे पहचानता नहीं है, क्योंकि यह एक बार बहुत पहले, बहुत समय पहले देखता था - #pragmaऔर जीसीसी , आदि)
जोनाथन लेफ़लर

15

लाना #pragma onceअपने हेडर फाइल के शीर्ष पर यह सुनिश्चित करेंगे कि यह केवल एक बार शामिल किया गया है। ध्यान दें कि #pragma onceमानक C99 नहीं है, लेकिन अधिकांश आधुनिक संकलक द्वारा समर्थित है।

एक विकल्प के लिए गार्ड शामिल हैं (जैसे #ifndef MY_FILE #define MY_FILE ... #endif /* MY_FILE */)


7

मुझे लगता है #pragmaकि एक निर्देश है जहां यदि आप चाहते हैं कि कोड विशिष्ट स्थान पर हो। तो ऐसी स्थिति में जब आप चाहते हैं कि प्रोग्राम काउंटर उस विशिष्ट पते से पढ़ें जहां ISR लिखा गया है तो आप उस स्थान पर ISR का उपयोग करके #pragma vector=ADC12_VECTORऔर उसका अनुसरण करके निर्दिष्ट कर सकते हैं। इंटरप्ट रोटाइन नाम और उसका विवरण


5

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

#pragma code BANK1
#pragma data BANK2

#pragma INT3 TimerHandler

3
सभी प्रस्ताव कार्यान्वयन-विशिष्ट हैं - #pragma एसटीडीसी को छोड़कर ... प्रैग्मस, जो सभी प्लेटफार्मों (C99 के अलावा) में मानकीकृत हैं।
जोनाथन लेफलर

4

उपरोक्त सभी उत्तर अच्छी व्याख्याएँ करते हैं, #pragmaलेकिन मैं एक छोटा सा उदाहरण जोड़ना चाहता था

मैं बस यह समझाना चाहता हूं simple OpenMP exampleकि #pragmaअपने काम करने के कुछ उपयोगों को प्रदर्शित करता है

OpenMp brieflyमल्टी-प्लेटफॉर्म साझा-मेमोरी समानांतर प्रोग्रामिंग के लिए एक कार्यान्वयन है (फिर हम कह सकते हैं कि यह machine-specificया है operating-system-specific)

उदाहरण के लिए चलते हैं

#include <stdio.h>
#include <omp.h>// compile with: /openmp

int main() {
   #pragma omp parallel num_threads(4)
   {
      int i = omp_get_thread_num();
      printf_s("Hello from thread %d\n", i);
   }
}

आउटपुट है

Hello from thread 0
Hello from thread 1
Hello from thread 2
Hello from thread 3

Note that the order of output can vary on different machines.

अब मैं आपको बताता हूँ कि क्या #pragmaकिया ...

यह ओएस को 4 थ्रेड्स पर कोड के कुछ ब्लॉक को चलाने के लिए कहता है

यह आप में से एक है many many applicationsजो छोटे के साथ कर सकता है#pragma

बाहर के नमूने के लिए खेद है OpenMP


3

यह एक प्रीप्रोसेसर निर्देश है जिसका उपयोग कुछ विशेषताओं को चालू या बंद करने के लिए किया जा सकता है।

यह दो प्रकार का होता है #pragma startup, #pragma exitऔर #pragma warn

#pragma startup कार्यक्रम स्टार्टअप पर बुलाया कार्यों को निर्दिष्ट करने की अनुमति देता है।

#pragma exit हमें प्रोग्राम से बाहर निकलने पर होने वाले कार्यों को निर्दिष्ट करने की अनुमति देता है।

#pragma warn किसी भी चेतावनी को दबाने के लिए कंप्यूटर को बताता है या नहीं।

#pragmaसंकलक को नियंत्रित करने के लिए कई अन्य शैलियों का उपयोग किया जा सकता है।


3

#pragma startup एक निर्देश है जिसका उपयोग मुख्य कार्य से पहले एक फ़ंक्शन को कॉल करने और मुख्य फ़ंक्शन के बाद किसी अन्य फ़ंक्शन को कॉल करने के लिए किया जाता है, जैसे

#pragma startup func1
#pragma exit func2

यहाँ, func1पहले चलता है mainऔर func2बाद में चलता है।

नोट: यह कोड केवल टर्बो-सी कंपाइलर में काम करता है। जीसीसी में इस कार्यक्षमता को प्राप्त करने, आप घोषणा कर सकते हैं func1और func2इस तरह:

void __attribute__((constructor)) func1();
void __attribute__((destructor)) func2();

2

इसे योग करने के लिए, #pragmaसंकलक को सामान करने के लिए कहता है। यहाँ कुछ तरीके हैं जो मैं इसका उपयोग करता हूँ:

  • #pragmaसंकलक चेतावनी को नजरअंदाज करने के लिए इस्तेमाल किया जा सकता है। उदाहरण के लिए, अंतर्निहित फ़ंक्शन घोषणाओं के बारे में जीसीसी को बंद करने के लिए, आप लिख सकते हैं:

    #pragma GCC diagnostic ignored "-Wimplicit-function-declaration"

    एक पुराने संस्करण को libportableयह आंशिक रूप से करता है ।

  • #pragma once, जब हेडर फ़ाइल के शीर्ष पर लिखा जाता है, तो हेडर फ़ाइल को एक बार शामिल करने का कारण होगा। एक बार समर्थन के लिए प्रगति की libportable जाँच करता है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.