123

デバッグ目的で、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)
4

10 に答える 10

203

プリプロセッサ マクロ__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__);
于 2010-05-17T14:27:31.933 に答える
66

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__);
于 2010-05-17T14:27:28.970 に答える
19

関数名、クラス、行番号などのデバッグ情報も含まれることを除いて、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) 成功!

于 2014-11-07T21:15:57.840 に答える
11

使用__LINE__(これは double-underscore LINE double-underscore です)、プリプロセッサはそれが見つかった行番号に置き換えます。

于 2010-05-17T14:27:30.033 に答える
9

チェックアウト__FILE____LINE__マクロ

于 2010-05-17T14:27:44.460 に答える
4

試してみて__FILE__ください__LINE__。また、役立つ
かもしれません。 ただし、クライアント側でプログラムをデバッグする必要があり、したがってこれらの情報をログに記録する必要がない限り、通常のデバッグを使用する必要があります。__DATE____TIME__

于 2010-05-17T15:24:07.143 に答える
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__or__func__のようなリテラルでそれらを使用することはできませんhere .

最終的に、C++ または C++11 を使用している場合、マクロを使用して呼び出し行を取得するよりも、これは非常に興味深い代替手段になる可能性があります。

于 2016-02-09T20:51:22.510 に答える
1

を使用__LINE__しますが、その型は何ですか?

LINE現在のソース行の推定行番号 (現在のソース ファイル内) (整数定数)。

整数定数として、コードは多くの場合、値がである__LINE__ <= INT_MAXと想定できるため、型は intです。

C で印刷するにprintf()は、一致する指定子が必要です: "%d". これは、C++ with ではそれほど問題ではありませんcout

辛辣な懸念:行番号がINT_MAX1を超える場合(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().

于 2020-02-19T21:07:32.193 に答える