読者です 読者をやめる 読者になる 読者になる

稲枝の押入れ

いなえが適当なことを書いては、しまっておく場所

__PRETTY_FUNCTION__マクロが使えない

__FUNCTION__

ちょっと気になることがあって小さい規模のコードを書いていたのだが、デバッグの時に今いる関数が表示できたら楽だなと思い、そんなマクロがあった気がするとか思いながら適当な文字列打ってたら__FUNCTION__マクロをサジェストに発見。

しかしこいつは関数の名前しか返してくれない。オーバーロードされた関数が複数あって、その中で__FUNCTION__マクロを使うような事があったら、実際にはどの関数が走っているのかがわからない。

__PRETTY_FUNCTION__

そんなわけで、型や引数の型なんかも返してくれるものないかなと思ったら__PRETTY_FUNCTION__マクロというものを発見。こいつは型や引数の型も返してくれるらしい。

よしこれだと書いてみると

C2065 '__PRETTY_FUNCTION__': 定義されていない識別子です。

とのこと。

こういった所謂「事前定義済みマクロ」はどうもコンパイラの独自実装のことが多いらしいので、そのへんが関係しているのかも?と思ったら、VSのサジェストでもちゃっかり出てきている。でもコンパイラさんはこんな識別子は知らないらしい。

ちょっと調べてみたらg++の独自実装だとか書いてあったけど、ますます何故サジェストが効いたのかわからなくなってきた。

原因が知りたいところではあるけれど、その前にまずは何とか動くようにしたい。

__FUNCSIG__

他にも型や引数の型を返してくれる事前定義済みマクロがないかなあと思って探していたら__FUNCSIG__マクロなるものを発見。これを使ったらうまく行った。

試しにmain関数の中で使ってみたら

int __cdecl main(void)

こんな感じで実行中関数の情報をくれた。

マイクロソフトの公式情報によると、__FUNCSIG__マクロは

__FUNCSIG__ Defined as a string literal that contains the signature of the enclosing function. The macro is defined only within a function. The __FUNCSIG__ macro is not expanded if you use the /EP or /P compiler option. When compiled for a 64-bit target, the calling convention is __cdecl by default. For an example of usage, see the __FUNCDNAME__ macro.

引用元
日本語がいい人はこっち

てな感じらしい。相も変わらず翻訳が意味わからなかったので原文で。まだ日本語訳してくれているだけありがたいので文句ばかりはいってられないけれど、マイクロソフトのあのわかりにくい翻訳は何とかならないのだろうか…

__func__

余談だけれど、「事前定義済みマクロ」はどうもコンパイラーの独自実装のことが多い、とさっき書いたけれど、その中でもこの関数名を表示する系のもののうち一部は、今では(という書き方をすると怒られそうなので補足しておくと一定の規格からは)規格として定義されているらしい。

例えば、C99では__FUNCTION__と同等の機能のものが__func__として追加されたそうな。ただし、

C++では現時点では定義が無いが、g++やclang/LLVMではC++コンパイル時にも利用できる。 g++の場合、C++で使用した場合は __FUNCTION__ とは違い関数名や引数はクラス名付きで得られる。

引用元

ということで、C++だと同等とは言えないみたいだけど。

まとめ

簡単にまとめると

  • __FUNCTION__
    • 関数の名前のみを得られる
  • __func__
    • C99で定義
    • __FUNCTION__と基本的に同じ
    • C++環境では違うことも?
  • __FUNCSIG__
    • 関数の型と名前と引数の型を得られる
  • __PRETTY_FUNCTION__
    • 関数の型と名前と引数の型を得られる(らしい)
    • VS環境ではコンパイル時にエラーが出て使えない(サジェストには表示される)
  • __FUNCDNAME__
    • 関数の名前を装飾名付で得られる

という感じ。一番下のものはこの記事では触れてませんが気になったら調べてみてください。さっきのMSのページにも書いてます。

あと、ここではわかりやすいように「得られる」と書いたが、厳密には「定義されている」だと思う。関数ではなくマクロなので。

もし__PRETTY_FUNCTION__が僕のVS環境下でコンパイルするとエラーが出るのか、思い当たる人は是非教えていただきたいです…