Cでの#pragmaの使用


117

いくつかの用途は何ですか#pragmaCでの例を挙げて、?


2
#pragmaディレクティブは前処理段階を乗り越えます。異なり#include#define
smwikipedia 2018


@smwikipediaあなたはいくつかのプラグマが生き残ることを意味しますか?#pragma onceはプリプロセッサディレクティブですが、#pragma packはコンパイラディレクティブです
Lewis Kelsey

回答:


66

#pragma マシン固有またはオペレーティングシステム固有のコンパイラディレクティブ用です。つまり、すべてのマシンとオペレーティングに適用されるかどうかに関係なく、何かを行う、オプションを設定する、何らかのアクションを実行する、デフォルトをオーバーライドするなど、コンパイラに指示します。システム。

詳細については、msdnを参照してください。


11
「それはすべてのマシンとオペレーティングシステムに当てはまるかもしれないし、当てはまらないかもしれません。」-同じマシン上の異なるコンパイラ。そして、それはコンパイラによって異なることを意味するかもしれません。
スティーブジェソップ

53

#pragma Cで実装固有の何かを行うために使用されます。つまり、イデオロギー的に独断的ではなく、現在のコンテキストに対して実用的です。

私が定期的に使用しているのは#pragma pack(1)、組み込みソリューションでメモリ空間をさらに絞り出そうとしているところです。そうしないと、構造体の配列が8バイトアライメントになってしまいます。

#dogmaまだ残念です。楽しそう ;)


@ShaneMacLaughlin、pragma(1)速度も大幅に向上しませんか?stackoverflow.com/questions/3318410/…を
Pacerier

4
@Pacerier、通常はありません。jalfsコメントによると、32ビットプロセッサの4バイト境界または64ビットプロセッサの8バイト境界に配置されたデータは、通常、1回の操作でロードおよび格納されます。より小さい境界に配置されたデータは、ロードまたは保存するために複数の操作を必要とします。これは遅いです。
SmacL

35

#pragmasは非常にコンパイラに依存し、移植性がないため、できれば#pragmasの使用はできるだけ避けます。それらを移植可能な方法で使用したい場合は、すべてのプラグマを#if/ #endifペアで囲む必要があります。GCCはプラグマの使用を推奨せず、他のコンパイラとの互換性のために実際にはそれらの一部のみをサポートします。GCCには、他のコンパイラーがプラグマを使用するのと同じことを行う他の方法があります。

たとえば、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)

GCCコードはより移植性があります。GCC以外のコンパイラでコンパイルしたい場合は、

#define __attribute__(x)

一方、MSVCコードを移植する場合は、各プラグマを#if/ #endifペアで囲む必要があります。きれいじゃない。


3
それで、MSVCでGCCコードをコンパイルし、構造をパックする必要がある場合、どのように正確に行うのですか?
SmacL 2009年

2
gccの場合、それは struct __attribute__((__packed__)) PackedStructure
Laurent Debricon、2010

#pragma onceは、現実的には「コンパイラーに依存し、移植不可能」ではありません。それは...すべての主要なプラットフォームと多く、主要でないプラットフォームでサポートされます en.wikipedia.org/wiki/Pragma_once#Portability
xaxxon

1
C99とC11の両方に(C11)§6.10.6プラグマディレクティブと¶1 が含まれていることに注意してください。実装によって認識されないそのようなプラグマは無視されます。§6.8.6にありましたが、C90もそれを述べています。(それが実行される場合、これはGCCの非準拠になりhack-を参照して、それが認識されないプラグマに遭遇したとき、それは非常に、非常に長い時間前にすると、一度行うために使用されるように#pragmaし、GCCなど)
ジョナサン・レフラー

15

#pragma onceヘッダーファイルの先頭に置くと、ヘッダーファイルが1回だけ含まれるようになります。これ#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 STDC ...プラグマは除きます。これは、すべてのプラットフォームで標準化されています(C99に追加)。
Jonathan Leffler、

4

上記のすべての答えは良い説明です#pragmaが、小さな例を追加したかった

simple OpenMP example#pragmaその仕事をするためのいくつかの使用法を示すことを説明したいだけです

OpenMPのはbriefly(そして、我々はそれがだと言うことができますマルチプラットフォーム共有メモリ並列プログラミングのための実装ですmachine-specificoperating-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スレッドでコードのブロックを実行するようにOSに指示します

これはmany many applicationsあなたが少しでできることの1つにすぎません#pragma

外側のサンプルで申し訳ありません OpenMP


3

これは、特定の機能をオンまたはオフにするために使用できるプリプロセッサディレクティブです。

これは、2つのタイプがあり#pragma startup#pragma exitそして#pragma warn

#pragma startup プログラムの起動時に呼び出される関数を指定できます。

#pragma exit プログラムの終了時に呼び出される関数を指定できます。

#pragma warn 警告を抑制するかどうかをコンピュータに指示します。

他の多くの#pragmaスタイルを使用してコンパイラを制御できます。


3

#pragma startup メイン関数の前に関数を呼び出し、メイン関数の後に別の関数を呼び出すために使用されるディレクティブです。例:

#pragma startup func1
#pragma exit func2

ここでfunc1は、前mainfunc2実行され、後に実行されます。

注:このコードはTurbo-Cコンパイラでのみ機能します。GCCでこの機能を実現するにはfunc1、次のfunc2ように宣言して好きなようにすることができます。

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

2

それを合計するには、#pragmaものを行うようにコンパイラに指示します。ここに私がそれを使用するいくつかの方法があります:

  • #pragmaコンパイラの警告を無視するために使用できます。たとえば、暗黙的な関数宣言についてGCCをシャットダウンするには、次のように記述します。

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

    古いバージョンのlibportableは、これを移植可能に実行します。

  • #pragma once、ヘッダーファイルの先頭に記述した場合、そのヘッダーファイルは一度だけインクルードされます。プラグマを一度サポートするlibportable かどうかチェックします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.