デバッグ目的で、C /C++ コンパイラの行番号を取得できますか? (特定のコンパイラの標準的な方法または特定の方法)
例えば
if(!Logical)
printf("Not logical value at line number %d \n",LineNumber);
// How to get LineNumber without writing it by my hand?(dynamic compilation)
デバッグ目的で、C /C++ コンパイラの行番号を取得できますか? (特定のコンパイラの標準的な方法または特定の方法)
例えば
if(!Logical)
printf("Not logical value at line number %d \n",LineNumber);
// How to get LineNumber without writing it by my hand?(dynamic compilation)
プリプロセッサ マクロ__LINE__
と__FILE__
. これらは定義済みマクロであり、C/C++ 標準の一部です。前処理中に、現在の行番号を表す整数を保持する定数文字列と現在のファイル名にそれぞれ置き換えられます。
その他のプリプロセッサ変数:
__func__
: 関数名 (これはC99の一部であり、すべての C++ コンパイラがサポートしているわけではありません)__DATE__
: "Mmm dd yyyy" 形式の文字列__TIME__
: "hh:mm:ss" 形式の文字列あなたのコードは次のようになります:
if(!Logical)
printf("Not logical value at line number %d in file %s\n", __LINE__, __FILE__);
C++ 標準の一部として、使用できる定義済みマクロがいくつか存在します。C++ 標準のセクション 16.8 では、とりわけ__LINE__
マクロが定義されています。
__LINE__
:現在のソース行の行番号 (10 進定数)。
__FILE__
:ソースファイルの推定名 (文字列リテラル)。
__DATE__
:ソースファイルの翻訳日(文字列リテラル…)
__TIME__
:ソースファイルの翻訳時刻(文字列リテラル…)
__STDC__
:__STDC__
定義済みかどうか
__cplusplus
:名前__cplusplus
は、199711Lの値に定義されます。 C++ 翻訳単位のコンパイル
したがって、コードは次のようになります。
if(!Logical)
printf("Not logical value at line number %d \n",__LINE__);
関数名、クラス、行番号などのデバッグ情報も含まれることを除いて、printf()と同じ動作のマクロを使用できます。
#include <cstdio> //needed for printf
#define print(a, args...) printf("%s(%s:%d) " a, __func__,__FILE__, __LINE__, ##args)
#define println(a, args...) print(a "\n", ##args)
これらのマクロは、java スタックトレースのような情報を含めながら、printf()と同じように動作する必要があります。メインの例を次に示します。
void exampleMethod() {
println("printf() syntax: string = %s, int = %d", "foobar", 42);
}
int main(int argc, char** argv) {
print("Before exampleMethod()...\n");
exampleMethod();
println("Success!");
}
次の出力が得られます。
main(main.cpp:11) exampleMethod() の前...
exampleMethod(main.cpp:7) printf() 構文: string = foobar, int = 42
main(main.cpp:13) 成功!
使用__LINE__
(これは double-underscore LINE double-underscore です)、プリプロセッサはそれが見つかった行番号に置き換えます。
チェックアウト__FILE__
と__LINE__
マクロ
試してみて__FILE__
ください__LINE__
。また、役立つ
かもしれません。
ただし、クライアント側でプログラムをデバッグする必要があり、したがってこれらの情報をログに記録する必要がない限り、通常のデバッグを使用する必要があります。__DATE__
__TIME__
私も現在この問題に直面しており、ここで尋ねられた別の有効な質問に回答を追加できないため、関数が呼び出された場所の行番号のみを取得するという問題の解決策の例を提供しますテンプレートを使用した C++。
背景: C++ では、非型整数値をテンプレート引数として使用できます。これは、テンプレート引数としてのデータ型の一般的な使用法とは異なります。したがって、関数呼び出しにそのような整数値を使用するという考え方です。
#include <iostream>
class Test{
public:
template<unsigned int L>
int test(){
std::cout << "the function has been called at line number: " << L << std::endl;
return 0;
}
int test(){ return this->test<0>(); }
};
int main(int argc, char **argv){
Test t;
t.test();
t.test<__LINE__>();
return 0;
}
出力:
関数は行番号で呼び出されました: 0
関数は行番号で呼び出されました: 16
ここで言及すべきことの 1 つは、C++11 標準では、テンプレートを使用して関数に既定のテンプレート値を与えることができるということです。非型引数の C++11 より前のデフォルト値は、クラス テンプレート引数に対してのみ機能するようです。したがって、C++11 では、上記のように関数定義を重複させる必要はありません。C++11 では、 const char* テンプレート引数を持つことも有効ですが、__FILE__
or__func__
のようなリテラルでそれらを使用することはできませんhere .
最終的に、C++ または C++11 を使用している場合、マクロを使用して呼び出し行を取得するよりも、これは非常に興味深い代替手段になる可能性があります。
を使用__LINE__
しますが、その型は何ですか?
LINE現在のソース行の推定行番号 (現在のソース ファイル内) (整数定数)。
整数定数として、コードは多くの場合、値がである__LINE__ <= INT_MAX
と想定できるため、型は int
です。
C で印刷するにprintf()
は、一致する指定子が必要です: "%d"
. これは、C++ with ではそれほど問題ではありませんcout
。
辛辣な懸念:行番号がINT_MAX
1を超える場合(16 ビットではある程度考えられるint
)、コンパイラが警告を生成することを願っています。例:
format '%d' expects argument of type 'int', but argument 2 has type 'long int' [-Wformat=]
あるいは、コードによって、より広い型を強制してそのような警告を未然に防ぐことができます。
printf("Not logical value at line number %ld\n", (long) __LINE__);
//or
#include <stdint.h>
printf("Not logical value at line number %jd\n", INTMAX_C(__LINE__));
避けるprintf()
すべての整数制限を回避するには: stringify . コードはprintf()
呼び出しなしで直接出力できます: エラー処理で避けるべき良いこと2 .
#define xstr(a) str(a)
#define str(a) #a
fprintf(stderr, "Not logical value at line number %s\n", xstr(__LINE__));
fputs("Not logical value at line number " xstr(__LINE__) "\n", stderr);
1確かに、このような大きなファイルを作成するプログラミング方法は適切ではありませんが、機械で生成されたコードは高くなる可能性があります。
2デバッグ中に、コードが期待どおりに機能しないことがあります。*printf()
canのような複雑な関数を呼び出すと、単純なfputs()
.