アーカイブ:_Pragma演算子ではまりました。
高木です。おはようございます。
先日お伝えしたように、『組込み現場の「C++」プログラミング 明日から使える徹底入門』の静的HTML化が完了しました。
これに伴い、http://embedded.cloverfield.jp/ は近日中に閉鎖する予定です。
8月中はアクセスできますが、その後はいつまで残るかお約束できません。
そういうこともあって、他の有益なブログ記事があれば残しておきたいと考えました。
ところが、いざ調べるとほとんどないのです。
今回はかろうじて残しておきたいと感じた記事をこちらに再掲したいと思います。
2016年4月12日の記事です。
最近になって使い始めた_Pragma演算子ですが、ちょっとはまったことがあったので備忘録として書いておくことにします。
_Pramga演算子というのは、C99から導入された前処理演算子です。
現在ではC++にも導入され、C++11以降で使えるようになっています。
この_Pragma演算子ですが、複数の処理系に共通のソースファイルを書くときには重宝します。
とくに組込みでは、セクションやら境界調整やら、その他処理系の独自拡張を使うために#pragma指令を使う機会が多いので、結構登場する機会があります。
今回はまった内容は次のようなものです。
1 | #pragma section セクション名 |
上のような#pragma指令の代わりに次のようなマクロを定義しました。
1 | #define SECTION(name) _Pragma("section " #name) |
_Pragma演算子は、_Prgma(文字列リテラル)
のように記述します。
上のマクロは、セクション名だけを指定させて、文字列リテラルを連結しようとしたのです。
Cでは、文字列リテラルを並べて書けば連結することができます。
たとえば、"abc" "123"
のように書けば"abc123"
と解釈されるはずだからです。
ところが、どういうわけかコンパイルエラーになってしまいます。
最初、どういうことかよくわかりませんでした。
しかし、すぐに原因がわかりました。
_Pragma演算子は前処理演算子です。
前処理演算子ということは、前処理指令が実行される翻訳段階(4)で処理されます。
ところが、文字列リテラルが連結されるのはもっと後の段階、すなわち翻訳段階(6)なのです。
これでは、先ほどのようなマクロがうまくいくはずがありません。
仕方がないので、マクロを次のように定義し直すことにしました。
1 2 | #define SECTION(name) PRAGMA(section name) #define PRAGMA(...) _Pragma(#__VA_ARGS__) |
今度はうまくいくようです。
Cを使っていると、わかっているつもりでもこういう失敗をときどきやってしまいます。
さすがに同じ失敗はもうしないでしょうけど……。