以前から存在は知っていたけれど、一度も使ったことがないものというのは少なからずあります。
私にとって、_Pragma演算子もそのひとつでした。
_Pragma演算子というのはC99で導入された前処理演算子で、C++でもC++11から導入されました。
これは、もともとあった#pragma指令を演算子化したもので、うまく使えば結構便利です。
なぜ_Pragma演算子を使う機会がなかったかというと、ひとつは、最近はC++やC#を使う機会の方が多く、Cを使う機会があまりなかったことがあります。
もうひとつは、特定のコンパイラに依存するようなコードは可能な限り避けるようにしていたためです。
そんな私ですが、先日、ついに_Pragma演算子を使うことになったのです。
どういう状況だったかというと、WindowsとルネサスのRXマイコンでコードを共有化する必要があり、なおかつWindowsではOpenMPを使うというものです。
OpenMPでfor文を並列化するには次のように書かなければなりません。
#pragma omp parallel for for (int i = 0; i < N; i++) ...
#pragma指令なので、OpenMPに対応しない処理系であれば通常無視されます。
たまたま同じ構文に合致する別の#pragma指令が存在する可能性もゼロではありませんが、まず考慮する必要はないでしょう。
少なくともRXマイコンのコンパイラにはありません。
ただ、そうはいっても、うるさい警告が出たりすることはありますし、何といっても気持ち悪いので、通常は次のようにします。
#ifdef _OPENMP #pragma omp parallel for #endif for (int i = 0; i < N; i++) ...
だんだんコードが汚くなってきましたね。
こういうのを、並列化するところにすべて入れていくのは気が滅入ります。
そこで_Pragma演算子の登場です。
#ifdef _OPENMP #define OMP_PARALLEL_FOR _Pragma("omp parallel for") #else #define OMP_PARALLEL_FOR #endif
のようにマクロ化しておけば、以降は
OMP_PARALLEL_FOR for (int i = 0; i < N; i++) ...
と書くだけでよくなります。
何なら、
#ifdef _OPENMP #define omp_parallel_for _Pragma("omp parallel for") for #else #define omp_parallel_for for #endif
としておけば、
omp_parallel_for (int i = 0; i < N; i++) ...
のようにすることもできます。
これならかなり気楽に使えそうです。
マイコンのプログラミングでは、関数やオブジェクトをどのセクションに配置するかなど、#pragma指令を使う機会が多々あります。
以前はC99に対応していないために_Pragma演算子が使えないことが多かったのですが、現在では主要な処理系がC99に対応しています(C11はまだまだですが……)。
今後は_Pragma演算子を普通に使えそうですね。
