C/C++ line number
C++CC PreprocessorLine NumbersDynamic CompilationC++ Problem Overview
In the sake of debugging purposes, can I get the line number in C/C++ compilers? (standard way or specific ways for certain compilers)
e.g
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++ Solutions
Solution 1 - C++
You should use the preprocessor macro __LINE__
and __FILE__
. They are predefined macros and part of the C/C++ standard. During preprocessing, they are replaced respectively by a constant string holding an integer representing the current line number and by the current file name.
Others preprocessor variables :
__func__
: function name (this is part of C99, not all C++ compilers support it)__DATE__
: a string of form "Mmm dd yyyy"__TIME__
: a string of form "hh:mm:ss"
Your code will be :
if(!Logical)
printf("Not logical value at line number %d in file %s\n", __LINE__, __FILE__);
Solution 2 - C++
As part of the C++ standard there exists some pre-defined macros that you can use. Section 16.8 of the C++ standard defines amongst other things, the __LINE__
macro.
> __LINE__
: The line number of the current source line (a decimal
> constant).
> __FILE__
: The presumed name of the source file (a character string
> literal).
> __DATE__
: The date of translation of the source file (a character string
> literal...)
> __TIME__
: The time of translation of the source file (a character string
> literal...)
> __STDC__
: Whether__STDC__
is predefined
> __cplusplus
: The name __cplusplus
is defined to the value 199711L when
> compiling a C ++ translation unit
So your code would be:
if(!Logical)
printf("Not logical value at line number %d \n",__LINE__);
Solution 3 - C++
You could use a macro with the same behavior as printf(), except that it also includes debug information such as function name, class, and line number:
#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)
These macros should behave identically to printf(), while including java stacktrace-like information. Here's an example main:
void exampleMethod() {
println("printf() syntax: string = %s, int = %d", "foobar", 42);
}
int main(int argc, char** argv) {
print("Before exampleMethod()...\n");
exampleMethod();
println("Success!");
}
Which results in the following output:
> main(main.cpp:11) Before exampleMethod()...
> exampleMethod(main.cpp:7) printf() syntax: string = foobar, int = 42
> main(main.cpp:13) Success!
Solution 4 - C++
Use __LINE__
(that's double-underscore LINE double-underscore), the preprocessor will replace it with the line number on which it is encountered.
Solution 5 - C++
C++20 offers a new way to achieve this by using std::source_location. This is currently accessible in gcc an clang as std::experimental::source_location
with #include <experimental/source_location>
.
The problem with macros like __LINE__
is that if you want to create for example a logging function that outputs the current line number along with a message, you always have to pass __LINE__
as a function argument, because it is expanded at the call site.
Something like this:
void log(const std::string msg) {
std::cout << __LINE__ << " " << msg << std::endl;
}
Will always output the line of the function declaration and not the line where log
was actually called from.
On the other hand, with std::source_location
you can write something like this:
#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;
}
Here, loc
is initialized with the line number pointing to the location where log
was called.
You can try it online here.
Solution 6 - C++
Checkout __FILE__
and __LINE__
macros
Solution 7 - C++
Try __FILE__
and __LINE__
.
You might also find __DATE__
and __TIME__
useful.
Though unless you have to debug a program on the clientside and thus need to log these informations you should use normal debugging.
Solution 8 - C++
For those who might need it, a "FILE_LINE" macro to easily print file and line:
#define STRINGIZING(x) #x
#define STR(x) STRINGIZING(x)
#define FILE_LINE __FILE__ ":" STR(__LINE__)
Solution 9 - C++
Since i'm also facing this problem now and i cannot add an answer to a different but also valid question asked here, i'll provide an example solution for the problem of: getting only the line number of where the function has been called in C++ using templates.
Background: in C++ one can use non-type integer values as a template argument. This is different than the typical usage of data types as template arguments. So the idea is to use such integer values for a function call.
#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;
}
Output:
> the function has been called at line number: 0 > > the function has been called at line number: 16
One thing to mention here is that in C++11 Standard it's possible to give default template values for functions using template__FILE__
or __func__
as mentioned here.
So in the end if you're using C++ or C++11 this might be a very interesting alternative than using macro's to get the calling line.
Solution 10 - C++
Use __LINE__
, but what is its type?
> LINE The presumed line number (within the current source file) of the current source line (an integer constant).
As an integer constant, code can often assume the value is __LINE__ <= INT_MAX
and so the type is int
.
To print in C, printf()
needs the matching specifier: "%d"
. This is a far lesser concern in C++ with cout
.
Pedantic concern: If the line number exceeds INT_MAX
1 (somewhat conceivable with 16-bit int
), hopefully the compiler will produce a warning. Example:
format '%d' expects argument of type 'int', but argument 2 has type 'long int' [-Wformat=]
Alternatively, code could force wider types to forestall such warnings.
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__));
Avoid printf()
To avoid all integer limitations: stringify. Code could directly print without a printf()
call: a nice thing to avoid in error handling2 .
#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 Certainly poor programming practice to have such a large file, yet perhaps machine generated code may go high.
2 In debugging, sometimes code simply is not working as hoped. Calling complex functions like *printf()
can itself incur issues vs. a simple fputs()
.