_File_, _Line_, and _Function_ Usage in C++

__FILE__, __LINE__, and __FUNCTION__ usage in C++

__FUNCTION__ is non standard, __func__ exists in C99 / C++11. The others (__LINE__ and __FILE__) are just fine.

It will always report the right file and line (and function if you choose to use __FUNCTION__/__func__). Optimization is a non-factor since it is a compile time macro expansion; it will never affect performance in any way.

How do predefined macro's __FILE__, __LINE__, __func__ ,stringify(#) work?

How is a LINE macro represented in assembly code?

It's not. These are preprocessor macros. Once the preprocessor runs, they are replaced with literals.

For example, if you had this code:

void foo() {
printf("%d", __LINE__);
}

The preprocessor will turn it into this:

void foo() {
printf("%d", 2);
}

Mangling __FILE__ and __LINE__ in code for quoting?

You will have to use a function to perform the hashing and create a code from __LINE__ and __FILE__ as the C preprocessor is not able to do such complex tasks.

Anyway, you can take inspiration by this article to see if a different solution can be better suited to your situation.

Capture __LINE__ and __FILE__ without #define

Actually the preprocessor is the only choice when you want to work with line numbers and filenames.

For the compiler it's not possible to use line numbers and filenames as arguments for function calls (or storing them in a variable).

In my company we had the exactly same issue with logging. We ended up with an external script scanning the source files and then building proper functions to call.

Passing the caller __FILE__ __LINE__ to a function without using macro

So, you're looking to do logging (or something) with file & line info, and you would rather not use macros, right?

At the end of the day, it simply can't be done in C++. No matter what mechanism you chose -- be that inline functions, templates, default parameters, or something else -- if you don't use a macro, you'll simply end up with the filename & linenumber of the logging function, rather than the call point.

Use macros. This is one place where they are really not replaceable.

EDIT:

Even the C++ FAQ says that macros are sometimes the lesser of two evils.

EDIT2:

As Nathon says in the comments below, in cases where you do use macros, it's best to be explicit about it. Give your macros macro-y names, like COMMIT() rather than Commit(). This will make it clear to maintainers & debuggers that there's a macro call going on, and it should help in most cases to avoid collisions. Both good things.

How to get filename from __FILE__ and concat with __LINE__ at compile time

For your specific case (getting the filename without path and the line number) there are a few easier approaches that you might want to use:



1. Using __FILE_NAME__ instead of __FILE__

Both gcc and clang support the __FILE_NAME__ macro, that just resolves to the filename instead of the full file path.

  • clang builtin macros
  • gcc common macros

Utilizing those you can write it as a single macro:


#define STRINGIFY(x) STRINGIFY_IMPL(x)
#define STRINGIFY_IMPL(x) #x

#define FILENAME __FILE_NAME__ ":" STRINGIFY(__LINE__)

// Usage:
constexpr char* foo = FILENAME;
std::cout << foo << std::endl;

msvc unfortunately doesn't offer the __FILE_NAME__ macro, but you could utilize the /FC compiler switch to specify if you want the full path for __FILE__ or just the filename.

--

2. Let the compiler do the string concatenation

Adjacent character sequences are automatically combined by the compiler - e.g. "a" "b" "c" would be combined into "abc".

You can use this to let the compiler do the concatenation for you.

After that we can just increment the pointer to that combined string past the last slash to trim off the path:

#define STRINGIFY(x) STRINGIFY_IMPL(x)
#define STRINGIFY_IMPL(x) #x
#define FILENAME __FILE__ ":" STRINGIFY(__LINE__)

constexpr const char* filename_without_path(const char* path) {
const char* result = path;
while(*path != '\0')
if(*path++ == '/') result = path;

return result;
}

// Usage:
constexpr const char* foo = filename_without_path(FILENAME);
std::cout << foo << std::endl;


NULL_CLASS_PTR_DEREFERENCE when using __FILE__, __LINE__ and __FUNCTION__ in log macro

NULL_CLASS_PTR_DEREFERENCE means that something with this pointer is wrong - this is NULL.

This could happen if a non-virtual member function is called on a null pointer at the first member accessed through this nullptr this.

You need to look one step back on the stack and make sure this does not happen at the caller site.



Related Topics



Leave a reply



Submit