Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

__func__ or __FUNCTION__ or manual const char* id?

Tags:

c

I'm wondering how widely are __func__ (part of C99, but I'm compiling as C89) and __FUNCTION__ supported.

I have an old code base that is mostly using manual const char* id; variables that are then passed to various (mostly logging) functions. I would like to get rid of this and move the function name into a macro.

like image 650
Šimon Tóth Avatar asked Aug 10 '11 09:08

Šimon Tóth


2 Answers

The predefined identifier __func__ was added to the 1999 ISO C standard; the older 1990 C standard doesn't have it.

Support for __func__ in pre-C99 compilers will depend on which compiler you're using.

Modern versions of gcc support __func__ even in C90 mode (-ansi or -std=c89).

Before __func__ was added to the standard, gcc implemented its own equivalent extension, but with the name __FUNCTION__. (gcc also supports __PRETTY_FUNCTION__, which is identical to __func__ and __FUNCTION__ for C, but provides more information in C++.)

The gcc manual gives some advice:

__FUNCTION__ is another name for __func__. Older versions of GCC recognize only this name. However, it is not standardized. For maximum portability, we recommend you use __func__, but provide a fallback definition with the preprocessor:

 #if __STDC_VERSION__ < 199901L
 # if __GNUC__ >= 2
 #  define __func__ __FUNCTION__
 # else
 #  define __func__ "<unknown>"
 # endif
 #endif

which implies that gcc added support for __FUNCTION__ in version 2. gcc 2.0 was released in 1992; you're very unlikely to be using a version of gcc that doesn't support at least __FUNCTION__, if not __func__.

Note that since __func__ and __FUNCTION__ are predefined identifiers, not macros, you only need the #define once, not in each function. On the other hand, you can't use #ifdef __func__ or #ifdef __FUNCTION__ to detect the level of support.

As for other compilers, a quick experiment indicates that Microsoft Visual C++ 2010 Express supports __FUNCTION__, but not __func__ or __PRETTY_FUNCTION__, when compiling C code. The above block of code from the gcc manual compiles under MSVC, but it results in __func__ being defined as "<unknown>". It shouldn't be too difficult to adjust it to recognize that MSVC supports __FUNCTION__. (I don't know whether older versions do so.) You can probably use the predefined macro _MSC_VER for this. Microsoft's documentation says that support for __FUNCTION__ goes back at least to the 2003 release, which sets _MSC_VER to 1300, so changing the second line to

# if __GNUC >= 2 || _MSC_VER >= 1300

is a good start. (It may well have been supported in earlier releases.)

For compilers other than gcc and MSVC, you'll have to consult their respective documentation -- but in any case, the block of code recommended in the gcc manual should work for any compiler, at worst falling back to "<unknown>".

like image 77
Keith Thompson Avatar answered Nov 01 '22 15:11

Keith Thompson


The boost current_function.hpp header contains several #defines for the ways to get the current function on different platforms.

That's not to say that those platforms don't support other ways of getting the current function, but the choices made for boost are likely to represent nice (if not the nicest) ways of getting the information on those platforms.

An adaptation of this header for your code (and for C) could well be what you need.

like image 44
Sander De Dycker Avatar answered Nov 01 '22 14:11

Sander De Dycker