Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Treating __func__ as a string literal instead of a predefined identifier

Tags:

c

macros

I am using gcc to compile C99 code. I want to write a macro which will return a string containing the function name and line number.

This is what I have:

#define INFO_MSG  __FILE__ ":"__func__"()"

However, when I compile code which attempts to use this string, for example:

char buff[256] = {'\0'}
sprintf(buff, "Something bad happened here: %s, at line: %d", INFO_MSG, __LINE__);
printf("INFO: %s\n", buff);

I get the following error message:

error: expected ‘)’ before ‘__func__’

I have tracked the problem down to the macro. as when I remove __func__ from the macro, the code compiles correctly.

How do I fix the macro, so that I can include the predefined __func__ macro in my string?

like image 208
Homunculus Reticulli Avatar asked Aug 18 '13 12:08

Homunculus Reticulli


1 Answers

Judging from your comments, the objective is to have a macro which combines the file name and function name (and maybe line number) into a single string that can be passed as an argument to functions such as printf() or strcpy() or syslog().

Unfortunately, I don't think that's possible.

The C11 standard says:

ISO/IEC 9899:2011 §6.4.2.2 Predefined identifiers

¶1 The identifier __func__ shall be implicitly declared by the translator as if, immediately following the opening brace of each function definition, the declaration

static const char __func__[] = "function-name";

appeared, where function-name is the name of the lexically-enclosing function.

Therefore, __func__ is not a macro, unlike __FILE__ or __LINE__.

The related question What's the difference between __PRETTY_FUNCTION__, __FUNCTION__, __func__? covers some alternative names. These are GCC-specific extensions, not standard names. Moreover, the GCC 4.8.1 documentation says:

These identifiers are not preprocessor macros. In GCC 3.3 and earlier, in C only, __FUNCTION__ and __PRETTY_FUNCTION__ were treated as string literals; they could be used to initialize char arrays, and they could be concatenated with other string literals. GCC 3.4 and later treat them as variables, like __func__. In C++, __FUNCTION__ and __PRETTY_FUNCTION__ have always been variables.

There are sound reasons why these cannot be preprocessor constructs. The preprocessor does not know what a function is and whether the text it is processing is in the scope of a function, or what the name of the enclosing function is. It is a simple text processor, not a compiler. Clearly, it would be possible to build that much understanding into the preprocessor (solely for the support of this one feature), but it is not required by the standard, and neither should it be required by the standard.

Unfortunately, though, I think it means that attempts to combine __func__ (by any spelling) with __FILE__ and __LINE__ in a single macro to generate a single string literal are doomed.

Clearly, you can generate the file name and line number as a string using the standard two-step macro mechanism:

#define STR(x) #x
#define STRINGIFY(x) STR(x)

#define FILE_LINE __FILE__ ":" STRINGIFY(__LINE__)

You can't get the function name into that as part of a string literal, though.

There are arguments that the file name and line number are sufficient to identify where the problem is; the function name is barely necessary. It is more cosmetic than functional, and slightly helps programmers but not other users.

like image 175
Jonathan Leffler Avatar answered Oct 23 '22 01:10

Jonathan Leffler