web-dev-qa-db-ja.com

Cでの#pragmaの使用

Cでの#pragmaの使用例は何ですか?

107
srujan

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

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

60
Steven A. Lowe

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

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

残念ながら、まだ#dogmaがありません。楽しそう ;)

52
SmacL

通常、#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ペアで囲む必要があります。可愛くない。

32
Adam Rosenfield

#pragma onceをヘッダーファイルの先頭に配置すると、確実に1回だけ含まれます。 #pragma onceは標準C99ではありませんが、最新のコンパイラーのほとんどでサポートされていることに注意してください。

別の方法は、インクルードガードを使用することです(例:#ifndef MY_FILE #define MY_FILE ... #endif /* MY_FILE */

15
Schildmeijer

私が感じるものは#pragmaは、コードを特定の場所にしたい場合、たとえばISRが書き込まれている特定のアドレスからプログラムカウンターに読み取りたい状況の場合、ISRを指定できるディレクティブです#pragma vector=ADC12_VECTORを使用し、その後に割り込みrotines名とその説明が続く場所

7
sandeep

プラグマは定義により実装固有であるため、コンパイラのドキュメントを参照することをお勧めします。たとえば、組み込みプロジェクトでは、さまざまなセクションでコードとデータを見つけたり、割り込みハンドラーを宣言したりするためにそれらを使用しました。すなわち:

#pragma code BANK1
#pragma data BANK2

#pragma INT3 TimerHandler
5
Justin Love

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

#pragma startup func1
#pragma exit func2

ここで、func1mainの前に実行され、func2はその後に実行されます。

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

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

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

#pragma startup#pragma exit、および#pragma warnの2つのタイプがあります。

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

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

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

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

3
suresh pareek

上記のすべての回答は、#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つのスレッドでコードのブロックを実行するようにOSに指示します

これはmany many applicationsの1つにすぎません。小さな#pragma

外部サンプルOpenMPでごめんなさい

3

まとめると、#pragmaはコンパイラーに何かをするように指示します。使用方法は次のとおりです。

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

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

    libportable の古いバージョンはこれを行います portably

  • #pragma onceは、ヘッダーファイルの先頭に書き込まれると、そのヘッダーファイルが1回含まれます。 libportablechecks プラグマワンスサポート用。

2
MD XF