C++の__FILE__・__LINE__・__FUNCTION__とは?使い方を実例つきで解説
はじめに
C++には、あらかじめ定義された「定義済みマクロ」が複数用意されており、ソースファイル名・行番号・関数名といった情報をプログラムの中で手軽に取得できます。これらを活用すれば、エラーログの出力やデバッグ作業がぐっと効率的になります。本記事では、代表的な3つのマクロである __FILE__、__LINE__、__FUNCTION__ の使い方を、実際のコード例とともに解説します。
__FILE__:現在のファイルパスを取得する
__FILE__ は、コンパイル中のソースファイルのパスを文字列リテラルとして展開するマクロです。「どのファイルでエラーが発生したのか」をログに記録したい場合に特に役立ちます。
コード例
#include <iostream>
#include <string>
using namespace std;
void errorLog(const char* file, const string& msg) {
cerr << "[" << file << "] " << msg << endl;
}
#define LOG(msg) errorLog(__FILE__, msg)
int main() {
LOG("これはダミーのエラーです");
return 0;
}
出力結果
[D:\Misc C and C++ Questions\test_prog.cpp] これはダミーのエラーです
LOGマクロを呼び出すだけで、その呼び出し元のファイルパスが自動的にログへ出力されます。
__LINE__:現在の行番号を取得する
__LINE__ は、このマクロが記述されている行番号を整数値として展開します。ログ出力時に「ファイル内の何行目で問題が発生したか」を特定できるため、大規模なソースコードのデバッグで重宝します。
コード例
#include <iostream>
#include <string>
using namespace std;
void errorLog(int line, const string& msg) {
cerr << "[" << line << "] " << msg << endl;
}
#define LOG(msg) errorLog(__LINE__, msg)
int main() {
LOG("これはダミーのエラーです");
return 0;
}
出力結果
[12] これはダミーのエラーです
この例では、LOGマクロが12行目で展開されるため、行番号「12」が出力されています。
__FUNCTION__:現在の関数名を取得する
__FUNCTION__ は、現在実行中の関数名を文字列として返します。どの関数からログが出力されたのかを一目で判別できるため、ログの可読性が大きく向上します。
コード例
#include <iostream>
#include <string>
using namespace std;
void errorLog(const char* func, const string& msg) {
cerr << "[" << func << "] " << msg << endl;
}
#define LOG(msg) errorLog(__FUNCTION__, msg)
void TestFunction() {
LOG("関数から送信されました");
}
int main() {
TestFunction();
LOG("これはダミーのエラーです");
return 0;
}
出力結果
[TestFunction] 関数から送信されました [main] これはダミーのエラーです
なお、__FUNCTION__ はGCCやClangなどが提供する拡張機能で、厳密には標準規格外です。C++11以降では、同等の働きを持つ標準識別子 __func__ を使うことが推奨されます。
3つのマクロを組み合わせた実践的なログ出力
これらのマクロは単体でも有用ですが、組み合わせることでより詳細なログを1行で出力できます。以下は、ファイル名・行番号・関数名をすべて記録する実践的な例です。
#include <iostream>
#include <string>
using namespace std;
void errorLog(const char* file, int line,
const char* func, const string& msg) {
cerr << "[" << file << ":" << line
<< " (" << func << ")] " << msg << endl;
}
#define LOG(msg) errorLog(__FILE__, __LINE__, __FUNCTION__, msg)
int main() {
LOG("これはダミーのエラーです");
return 0;
}
出力結果
[test_prog.cpp:16 (main)] これはダミーのエラーです
まとめ
__FILE__ でファイル名、__LINE__ で行番号、__FUNCTION__ で関数名を取得できることを解説しました。これらの定義済みマクロをLOGマクロのような形でラップしておけば、問題の発生箇所を素早く特定できる高品質なログ機構を、ごく少ないコストで構築できます。日々のデバッグ作業にぜひ取り入れてみてください。
-
【C++入門】cin・cout・cerrストリームの基本と使い方を徹底解説
C++の標準入出力ストリームとは? C++におけるcin、cout、cerr、clogは、標準入力と標準出力を扱うためのストリームです。これらはすべて、iostreamヘッダファイルで定義されているストリームオブジェクトであり、C++プログラミングにおける入出力処理の基礎となります。 std::cin(標準入力ストリーム) std::cinは、istreamクラスのオブジェクトで、char型などのナロー文字に対応した標準入力ストリームを表します。C言語のstdinに相当します。標準入力ストリームは、環境によって決定される文字の入力元であり、通常はキーボードやファイルなど外部ソースからの入力と
-
C++のsigned(符号付き)とunsigned(符号なし)キーワードとは?違いと使い方を解説
C++における符号付き・符号なしデータ型の基本C++では、すべての数値型に対して「符号付き(signed)」か「符号なし(unsigned)」かを指定できます。たとえば、int型を宣言する際に正の整数のみを扱うよう指定することも可能です。特別な指定がない場合、すべての整数型はデフォルトで符号付き(signed)として扱われます。つまり、正負どちらの値も保持できるということです。一方、unsignedキーワードを使用すると、符号を持たない変数を宣言できます。サンプルコード#include<iostream>using namespace std;int main() { &