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
: 이름__cplusplus
C + + 변환 유닛을 컴파일 할 때 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_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()
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
'programing' 카테고리의 다른 글
반환을 위해 개체를 일반 유형으로 캐스팅 (0) | 2022.08.10 |
---|---|
C: loop int 초기 선언용 (0) | 2022.08.10 |
int vs 플로어에 캐스팅 (0) | 2022.08.10 |
Vuex ReferenceError가 정의되지 않았습니다.값을 올바르게 설정하려면 어떻게 해야 합니까? (0) | 2022.08.10 |
size_t는 C로 얼마입니까? (0) | 2022.08.10 |