デバッグのために、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__);
#define S1(N) #N
#define S2(N) S1(N)
#define LINESTR S2(__LINE__)
。c-faq.com/ansi/stringize.htmlを
__func__
はマクロではなく、暗黙的に宣言された変数です。
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)成功しました!
#include
に<stdio.h>
C ++ 20は、std :: source_locationを使用してこれを実現する新しい方法を提供します。これは、gccを打ち鳴らすには現在アクセス可能であるstd::experimental::source_location
と#include <experimental/source_location>
。
などのマクロの問題__LINE__
は、たとえば現在の行番号をメッセージとともに出力するロギング関数を作成する場合__LINE__
、呼び出しサイトで展開されるため、常に関数の引数として渡す必要があることです。このようなもの:
void log(const std::string msg) {
std::cout << __LINE__ << " " << msg << std::endl;
}
関数宣言の行を常に出力し、log
実際に呼び出された行は出力しません。一方、std::source_location
次のように書くことができます:
#include <experimental/source_location>
using std::experimental::source_location;
void log(const std::string msg, const source_location loc = source_location::current())
{
std::cout << loc.line() << " " << msg << std::endl;
}
ここでloc
は、log
が呼び出された場所を指す行番号で初期化されます。
ここでオンラインで試すことができます。
試してみてください__FILE__
と__LINE__
。
あなたも見つけ__DATE__
て__TIME__
便利かもしれません。
ただし、クライアント側でプログラムをデバッグする必要がなく、これらの情報をログに記録する必要がない限り、通常のデバッグを使用する必要があります。
raw code
ティックを使用してそれらにマークを付ける必要があります(このように: `__`)。@mmyersが助けようとしたが、彼はアンダースコアの1つだけをエスケープしたため、イタリックのマークアップ構文が残った。ここで反対投票は少し厳しいですが、私は同意します。
私もこの問題に直面していて、ここで尋ねられた別の有効な質問への回答を追加できないため、問題の解決策の例を提供します:関数が呼び出された場所の行番号のみを取得しますテンプレートを使用した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__
または__func__
言及したように、ここを。
したがって、最終的には、C ++またはC ++ 11を使用している場合、これはマクロを使用して呼び出し行を取得するよりも非常に興味深い代替手段になる可能性があります。
を使用しますが__LINE__
、そのタイプは何ですか?
LINE現在のソース行(整数定数)の(現在のソースファイル内の)推定行番号。
整数定数として、コードは値が__LINE__ <= INT_MAX
そうであると仮定することができるので、型は int
です。
Cで印刷するにprintf()
は、一致する指定子が必要です"%d"
。これは、C ++でを使用すると、はるかに問題が少なくなり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()
、単純な関数と比較して、それ自体で問題が発生する可能性がありますfputs()
。