programing

C/C++ 회선 번호

goodsources 2022. 8. 10. 22:24
반응형

C/C++ 회선 번호

디버깅을 위해 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__: "Mm dd yyy" 형식의 문자열
  • __TIME__: "hh:mm:ss" 형식의 문자열

코드는 다음과 같습니다.

if(!Logical)
  printf("Not logical value at line number %d in file %s\n", __LINE__, __FILE__);

C++20은 std::source_location을 사용하여 이를 실현하는 새로운 방법을 제공합니다.이것은 현재 gcc an clang에서 액세스 할 수 있습니다.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가 호출되었습니다.여기서 온라인으로 시도해 볼 수 있습니다.

C++ 표준의 일부로서 사용할 수 있는 몇개의 사전 정의 매크로가 있습니다.C++ 표준의 섹션 16.8은 특히 다음과 같이 정의하고 있습니다.__LINE__매크로를 사용합니다.

__LINE__: 현재 송신원 회선 번호(10 진수).
: 소스 파일의 예상 이름(문자 리터럴__FILE__).
__DATE__: 소스 파일의 변환 날짜(문자열 리터럴...)
__TIME__: 소스 파일의 변환 시간(문자열 리터럴...)
__STDC__: 유무__STDC__미리 정의되어 있습니다.
__cplusplus: 이름__cplusplusC + + 변환 유닛을 컴파일 할 때 199711L 값으로 정의됩니다.

암호는 다음과 같습니다.

if(!Logical)
  printf("Not logical value at line number %d \n",__LINE__);

파일이나 행을 간단하게 인쇄할 수 있는 「FILE_LINE」매크로입니다.

#define STRINGIZING(x) #x
#define STR(x) STRINGIZING(x)
#define FILE_LINE __FILE__ ":" STR(__LINE__)

체크아웃__FILE__그리고.__LINE__매크로

해라__FILE__그리고.__LINE__.
또,__DATE__그리고.__TIME__유용한.
단, 클라이언트측에서 프로그램을 디버깅해야 하기 때문에 이러한 정보를 기록할 필요가 없는 한 일반 디버깅을 사용해야 합니다.

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 stacktrace와 같은 정보를 포함하면서 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__, 하지만 그것의 종류는 무엇입니까?

LINE 현재 소스 라인의 추정 라인 번호(현재 소스 파일 내)입니다(정수 상수).

정수 상수로서 코드는 종종 값이 다음과 같이 가정할 수 있습니다.__LINE__ <= INT_MAX그래서 타입은int.

C로 인쇄하려면printf()에는 일치하는 지정자가 필요합니다."%d"이것은, C++ 에서는 크게 염려되지 않습니다.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()call: 에러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().

저도 지금 이 문제에 직면해 있기 때문에 여기서 묻는 질문에는 답변을 추가할 수 없기 때문에 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에서 호출되었습니다.

여기서 한 가지 언급해야 할 것은 C++11 Standard에서는 템플릿을 사용하여 함수의 기본 템플릿 값을 지정할 수 있다는 것입니다.C++11 이전에서는 non-type 인수의 기본값은 클래스 템플릿인수에 대해서만 기능하는 것으로 보입니다.따라서 C++11에서는 위와 같이 중복된 함수 정의를 가질 필요가 없습니다.C++11에서는 const char* template 인수를 사용할 수도 있지만 다음과 같은 리터럴에서는 사용할 수 없습니다.__FILE__또는__func__여기서 말한 바와 같이

따라서 최종적으로 C++ 또는 C++11을 사용하는 경우에는 매크로를 사용하여 콜라인을 취득하는 것보다 매우 흥미로운 대안이 될 수 있습니다.

사용하다__LINE__(이것은 더블 언더스코어 LINE 더블 언더스코어), 프리프로세서는 프리프로세서를 검출한 회선번호로 바꿉니다.

언급URL : https://stackoverflow.com/questions/2849832/c-c-line-number

반응형