C'de #pragma kullanımı


117

#pragmaÖrneklerle birlikte C'de bazı kullanım alanları nelerdir ?


2
#pragmadirektif, ön işleme aşamasında hayatta kalır. Aksine #includeve #define.
smwikipedia


@smwikipedia, bazı pragmaların hayatta kalacağını mı söylüyorsunuz? #pragma bir kez önişlemci yönergesidir ancak #pragma paketi bir derleyici yönergesidir
Lewis Kelsey

Yanıtlar:


66

#pragma makineye özgü veya işletim sistemine özgü derleyici yönergeleri içindir, yani derleyiciye bir şeyler yapmasını, bazı seçenekleri ayarlamasını, bazı eylemlerde bulunmasını, bazı varsayılanları geçersiz kılmalarını, vb. tüm makineler ve işletim için geçerli olabilecek veya olmayabilecek sistemleri.

Daha fazla bilgi için msdn'ye bakın .


11
"tüm makineler ve işletim sistemleri için geçerli olabilir veya olmayabilir." - ve aynı makinede farklı derleyiciler. Ve bu, farklı derleyicilerde farklı şeyler anlamına gelebilir.
Steve Jessop

53

#pragma C'de uygulamaya özgü bir şey yapmak için kullanılır, yani ideolojik olarak dogmatik olmaktan ziyade mevcut bağlam için pragmatik olun.

Düzenli olarak kullandığım şey #pragma pack(1), gömülü çözümlerde bellek alanımdan, aksi takdirde 8 bayt hizalamayla sonuçlanacak yapı dizileri ile daha fazla sıkmaya çalıştığım yerdir.

Yazık, #dogmahenüz sahip değiliz . Bu eğlenceli olurdu;)


@ShaneMacLaughlin, pragma(1)Hızı gerçekten de artırmıyor mu ? Stackoverflow.com/questions/3318410/… sayfasına
Pacerier

4
@Pacerier, genellikle değil. Jalfs yorumlarına göre, 32 bit işlemciler için 4 bayt sınırında veya 64 bit işlemciler için 8 bayt sınırında hizalanan veriler tipik olarak tek bir işlemde yüklenir ve depolanır. Daha küçük sınırlarla hizalanan verilerin yüklenmesi veya depolanması için birden fazla işlem gerekir. Bu daha yavaştır.
SmacL

35

Derleyiciye aşırı derecede bağımlı olduklarından ve taşınabilir olmadıklarından, genellikle mümkünse #pragmalardan kaçınmaya çalışırdım. Onları taşınabilir bir şekilde kullanmak istiyorsanız, her pragmayı bir #if/ #endifçifti ile çevrelemeniz gerekir . GCC, pragmaların kullanılmasını engeller ve gerçekten sadece bazılarını diğer derleyicilerle uyumluluk için destekler; GCC, diğer derleyicilerin pragmaları kullandıkları aynı şeyleri yapmanın başka yollarına sahiptir.

Örneğin, MSVC'de bir yapının sıkı bir şekilde paketlenmesini (yani üyeler arasında dolgu yapılmamasını) nasıl sağlayacağınız aşağıda açıklanmıştır:

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

GCC'de aynı şeyi şu şekilde yaparsınız:

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

GCC kodu daha taşınabilirdir, çünkü bunu GCC olmayan bir derleyici ile derlemek istiyorsanız tek yapmanız gereken

#define __attribute__(x)

Oysa MSVC kodunu taşımak istiyorsanız, her pragmayı bir #if/ #endifçifti ile çevrelemelisiniz . Güzel değil.


3
Öyleyse, GCC kodunu MSVC üzerinde derlemek istersem ve yapıyı paketlemem gerekirse, bunu tam olarak nasıl yaparım?
SmacL

2
Gcc için, bu struct __attribute__((__packed__)) PackedStructure
Laurent Debricon

#pragma, gerçekçi olarak "derleyiciye bağlı ve taşınabilir olmayan" değildir. Her büyük platformda ve büyük olmayan birçok platformda destekleniyor .. en.wikipedia.org/wiki/Pragma_once#Portability
xaxxon

1
C99 ve C11'in her ikisinin de (C11) §6.10.6 Pragma direktiflerini ve ¶1 içerdiğini unutmayın . Uygulama tarafından tanınmayan bu tür herhangi bir pragma ihmal edilir. C90 bile §6.8.6'da olmasına rağmen bunu söylüyor. (Bu, GCC'yi hacktanımadığı bir pragma ile karşılaştığında çalışıyorsa uyumsuz hale getirir , çok çok uzun zaman önce yaptığı gibi - bkz. #pragmaVe GCC , vb.)
Jonathan Leffler

15

#pragma onceBaşlık dosyanızın en üstüne koymak , yalnızca bir kez eklenmesini sağlayacaktır. Bunun #pragma oncestandart C99 olmadığını, ancak çoğu modern derleyici tarafından desteklendiğini unutmayın.

Bir alternatif dahil korumaları kullanmaktır (ör. #ifndef MY_FILE #define MY_FILE ... #endif /* MY_FILE */)


7

#pragmaBenim hissettiğim şey , kodun konuma özgü olmasını istiyorsanız, program sayacının ISR'nin yazıldığı belirli bir adresten okumasını istediğiniz bir durumu söylerseniz, o konumda #pragma vector=ADC12_VECTORISR'yi kullanarak ve aşağıdakini kullanarak belirtebilirsiniz: interrupt rotines adı ve açıklaması


5

En iyi tavsiyem, derleyicinizin belgelerine bakmaktır, çünkü pragmalar tanım gereği uygulamaya özgüdür. Örneğin, gömülü projelerde farklı bölümlerdeki kodu ve verileri bulmak veya kesme işleyicileri bildirmek için kullandım. yani:

#pragma code BANK1
#pragma data BANK2

#pragma INT3 TimerHandler

3
Tüm platformlarda (C99'a ek olarak) standartlaştırılmış #pragma STDC ... pragmaları dışında tüm pragmalar uygulamaya özeldir.
Jonathan Leffler

4

Yukarıdaki tüm cevaplar için güzel açıklamalar yapıyor #pragmaama küçük bir örnek eklemek istedim

Ben sadece işini yapmanın simple OpenMP examplebazı kullanımlarını gösteren bir#pragma

OpenMp briefly, çok platformlu paylaşılan bellek paralel programlama için bir uygulamadır (o zaman machine-specificya da diyebiliriz operating-system-specific)

hadi örneğe gidelim

#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);
   }
}

çıktı

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.

şimdi ne #pragmayaptığını söyleyeyim ...

OS'ye bazı kod bloğunu 4 iş parçacığı üzerinde çalıştırmasını söyler

bu many many applicationsküçük şeylerle yapabileceğiniz şeylerden sadece biri#pragma

dış örnek için özür dilerim OpenMP


3

Bu, belirli özellikleri açmak veya kapatmak için kullanılabilen bir ön işlemci yönergesidir.

Bu iki tip olduğu #pragma startup, #pragma exitve #pragma warn.

#pragma startup program başlangıcında çağrılan işlevleri belirlememize izin verir.

#pragma exit programdan çıkıldığında çağrılan fonksiyonları belirlememize izin verir.

#pragma warn bilgisayara herhangi bir uyarıyı engellemesini söyler.

#pragmaDerleyiciyi kontrol etmek için diğer birçok stil kullanılabilir.


3

#pragma startup ana işlevden önce bir işlevi çağırmak ve ana işlevden sonra başka bir işlevi çağırmak için kullanılan bir yönergedir, örn.

#pragma startup func1
#pragma exit func2

Burada func1önce koşuyor mainve func2sonra koşuyor.

NOT: Bu kod yalnızca Turbo-C derleyicisinde çalışır. GCC'de bu işlevselliği elde etmek için, şunları beyan edebilir func1ve func2beğenebilirsiniz:

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

2

Özetlemek gerekirse #pragma, derleyiciye bir şeyler yapmasını söyler. İşte onu kullanmamın birkaç yolu:

  • #pragmaderleyici uyarılarını yok saymak için kullanılabilir. Örneğin, GCC'nin örtük işlev bildirimleri hakkında susmasını sağlamak için şunu yazabilirsiniz:

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

    Eski bir sürümü libportablebunu taşınabilir bir şekilde yapar .

  • #pragma once, bir başlık dosyasının en üstüne yazıldığında, adı geçen başlık dosyasının bir kez eklenmesine neden olur. destek bir kez pragma için libportable kontrol eder .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.