I have a C++ library that uses the predefined macro __FUNCTION__, by way of crtdefs.h. The macro is documented here. Here is my usage:
my.cpp
#include <crtdefs.h>
...
void f()
{
L(__FUNCTIONW__ L" : A diagnostic message");
}
static void L(const wchar_t* format, ...)
{
const size_t BUFFERLENGTH = 1024;
wchar_t buf[BUFFERLENGTH] = { 0 };
va_list args;
va_start(args, format);
int count = _vsnwprintf_s(buf, BUFFERLENGTH, _TRUNCATE, format, args);
va_end(args);
if (count != 0)
{
OutputDebugString(buf);
}
}
crtdefs.h
#define __FUNCTIONW__ _STR2WSTR(__FUNCTION__)
The library (which is compiled as a static library, if that matters) is consumed by another project in the same solution, a WPF app written in C#.
When I compile the lib, I get this error:
identifier "L__FUNCTION__" is undefined.
According to the docs, the macro isn't expanded if /P or /EP are passed to the compiler. I have verified that they are not. Are there other conditions where this macro is unavailable?
You list the error as this:
identifier "L__FUNCTION__" is undefined.
Note it's saying "L__FUNCTION__" is not defined, not "__FUNCTION__".
Don't use __FUNCTIONW__ in your code. MS didn't document that in the page you linked, they documented __FUNCTION__. And you don't need to widen __FUNCTION__.
ETA: I also note that you're not assigning that string to anything or printing it in anyway in f().
Just use
L(__FUNCTION__ L" : A diagnostic message");
When adjacent string literals get combined, the result will be a wide string if any of the components were.
There's nothing immediately wrong with using L as the name of a function... it's rather meaningless however. Good variable and function identifiers should be descriptive in order to help the reader understand the code. But the compiler doesn't care.
Since your L function wraps vsprintf, you may also use:
L(L"%hs : A diagnostic message", __func__);
since __func__ is standardized as a narrow string, the %hs format specifier is appropriate.
The rule is found in 2.14.5p13:
In translation phase 6 (2.2), adjacent string literals are concatenated. If both string literals have the same encoding-prefix, the resulting concatenated string literal has that encoding-prefix. If one string literal has no encoding-prefix, it is treated as a string literal of the same encoding-prefix as the other operand. If a UTF-8 string literal token is adjacent to a wide string literal token, the program is ill-formed. Any other concatenations are conditionally-supported with implementation-defined behavior.
I think the definition of __FUNCTIONW__ is incorrect. (I know you did not write it.)
From: http://gcc.gnu.org/onlinedocs/gcc/Function-Names.html
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.
At least in current GCC then you cannot prepend L to __FUNCTION__, because it is like trying to prepend L to a variable. There probably was a version of VC++ (like there was of GCC) where this would have worked, but you are not using that version.
Related
I've just noticed that __func__, __FUNCTION__ and __PRETTY_FUNCTION__ aren't treated as preprocessor macros and they're not mentioned on the 16.8 Predefined macro names section of the Standard (N4527 Working Draft).
This means that they cannot be used in the string concatenation trick of phase 6:
// Valid
constexpr char timestamp[]{__FILE__ " has been compiled: " __DATE__ " " __TIME__};
// Not valid!!!
template <typename T>
void die() { throw std::runtime_error{"Error detected in " __PRETTY_FUNCTION__}; }
As far as I know, the __FILE__, __DATE__ and __TIME__ are translated to string literals as stated by the standard:
16.8 Predefined macro names [cpp.predefined]
__DATE__
The date of translation of the source file: a character string literal of the form "Mmm dd yyyy", where the names of the months are the same as those generated by the asctime function, and the first character of dd is a space character if the value is less than 10. If the date of translation is not
available, an implementation-defined valid date shall be supplied.
__FILE__
The presumed name of the current source file (a character string literal).
__TIME__
The time of translation of the source file: a character string literal of the form "hh:mm:ss" as in the time generated by the asctime function.
__func__ is mentioned by the standard as a function-local predefined variable of the form:
static const char __func__[] = "function-name ";
So the fact is that is a local variable hence the string concatenation trick doesn't works with it.
As for __FUNCTION__ and __PRETTY_FUNCTION__ aren't mentioned in the standard (are implementation defined?) but is a pretty safe bet to think that they would behave like __func__.
So the question is: Why __func__, __FUNCTION__ and __PRETTY_FUNCTION__ are function-local static constant array of characters while __FILE__, __DATE__ and __TIME__ are string literals? What's the rationale (if any) behind this decision?
Expanding __func__ at preprocessing time requires the preprocessor to know which function it's processing. The preprocessor generally doesn't know that, because parsing happens after the preprocessor is already done.
Some implementations combine the preprocessing and the parsing, and in those implementations, it would have been possible for __func__ to work the way you'd like it to. In fact, if I recall correctly, MSVC's __FUNCTION__ works like that. It's an unreasonable demand on implementations that separate the phases of translation though.
Code as below:
FILE *sfp;
....
void test(char *s, ...)
{
va_list ap;
va_start(ap, s);
vfprintf(sfp, s, ap);
fflush(sfp);
va_end(ap);
}
below compile error reported:
error: format string is not a string literal [-Werror,-Wformat-nonliteral]
vfprintf(sfp, s, ap);
How to fix this error?
A variable is never a string literal. A string literal is a sequence of characters surrounded by double quote marks (i.e. "foo").
The purpose of that warning is to warn you that the compiler cannot confirm that the types of the parameters given to vfptrintf match the format string. To get rid of that warning, you will need to either
Pass a literal format string to vfprintf (i.e. vfprintf(sfp, "%d\n", ap))
Disable (or rather, don't enable) that warning and accept that the compiler cannot warn you if your arguments don't match the format specifier.
Add the format attribute to your function declaration (thanks to #chris in the comments):
i.e.
__attribute__((format(printf, 2, 3)))
void test(FILE* sfp, const char *s, ...)
{
//...
}
Or with the standardized C++11 attribute syntax:
[[gnu::format(printf, 2, 3)]]
void test(FILE* sfp, const char *s, ...)
{
//...
}
Note that that last option is not a standard C++ attribute, and therefore will not work on all compilers. You may need something else to appease MSVC for example. By the standard, compilers should ignore unknown attributes if you use the C++11 syntax, but they may still emit a warning about it, putting you right back in the same situation you're in now.
You will also still provoke a warning if test is called with a second argument that is not itself a string literal.
As a side note, it doesn't look like clang can check the argument types of the va_list printf functions anyway, so -Wformat-nonliteral isn't actually helpful in this case. GCC does not emit this warning, likely for that exact reason.
The title is pretty clear: Is it safe to use basename (man 3 basename) with __FILE__ ?.
It compiles and seems to work fine, but basename's argument is char* (not const char*) and the man-page says:
Both dirname() and basename() may modify the contents of path, so it may be desirable to pass a copy when calling one of these functions.
So, this makes me worry.
Maybe the question should be more like: what is the type of __FILE__? Isn't it a string literal / const char*? But if it is, why there's no a compile-time error (const char* to char*)?
Read carefully basename(3) and notice:
Warning: there are two different functions basename() - see below.
and take care of the NOTES saying
There are two different versions of basename() - the POSIX version
described above, and the GNU version, which one gets after
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <string.h>
The GNU version never modifies its argument, and returns the empty
string when path has a trailing slash
(emphasis is mine)
Because it is said that the GNU version does not modify its argument, using it is safe with __FILE__
BTW, you could consider customizing your GCC (e.g. with MELT) to define some __builtin_basename which would compute the basename at compile time if given a string literal like __FILE__ or else invoke basename at runtime.
Notice that libgen.h has #define basename __xpg_basename
what is the type of __FILE__? Isn't it a string literal / const char*?
Yes. It's a string literal.
But if it is, why there's no a compile-time error (const char* to char*)?
Possibly because the implementation you use (glibc's) may be returning a pointer within the string literal you pass (i.e. it doesn't modify its input).
In any case, you can't rely on it for the above stated below.
C standard (c11, § 6.10.8.1) says the __FILE__ is a string literal:
__FILE__ The presumed name of the current source file (a character string siteral).
POSIX says:
The basename() function may modify the string pointed to by path,
and may return a pointer to internal storage. The returned pointer
might be invalidated or the storage might be overwritten by a
subsequent call to basename().
(emphasis mine).
So, no, it's not safe to call basename() with __FILE__. You can simply take a copy of __FILE__ and do basename() on it:
char *filename = strdup(__FILE__);
if (filename) {
/* error */
}
char *file_basename = basename(filename);
free(filename);
Since __FILE__ is a string literal, using an array is another option:
char filename[] = __FILE__;
char *file_basename = basename(filename);
The preprocessor can be used to replace certain keywords with other words using #define. For example I could do #define name "George" and every time the preprocessor finds 'name' in the program it will replace it with "George".
However, this only seems to work with code. How could I do this with strings and text? For example if I print "Hello I am name" to the screen, I want 'name' to be replaced with "George" even though it is in a string and not code.
I do not want to manually search the string for keywords and then replace them, but instead want to use the preprocessor to just switch the words.
Is this possible? If so how?
I am using C++ but C solutions are also acceptable.
#define name "George"
printf("Hello I am " name "\n");
Adjacent string literals are concatenated in C and C++.
Quotes from C and C++ Standard:
For C (quoting C99, but C11 has something similar in 6.4.5p5):
(C99, 6.4.5p5) "In translation phase 6, the multibyte character sequences specified by any sequence of adjacent character and identically-prefixed string literal tokens are concatenated into a single multibyte character sequence."
For C++:
(C++11, 2.14.5p13) "In translation phase 6 (2.2), adjacent string literals are concatenated."
EDIT: as requested, add quotes from C and C++ Standard. Thanks to #MatteoItalia for the C++11 quote.
#define name "George"
printf("Hello I am %s\n", name);
Here name will be replaced by "George"
Your issue is that the preprocessor will (wisely) not replace tokens that are inside string literals.
So you must either use a function like printf or a variable rather than the preprocessor, or pull the token out of the string like so:
#include <iostream>
#define name "George"
int main(int argc, char** argv) {
std::cout << "Hello I am " << name << std::endl;
}
is it possible to concatenate strings during preprocessing?
I found this example
#define H "Hello "
#define W "World!"
#define HW H W
printf(HW); // Prints "Hello World!"
However it does not work for me - prints out "Hello" when I use gcc -std=c99
UPD This example looks like working now. However, is it a normal feature of c preprocessor?
Concatenation of adjacent string litterals isn't a feature of the preprocessor, it is a feature of the core languages (both C and C++). You could write:
printf("Hello "
" world\n");
You can indeed concatenate tokens in the preprocessor, but be careful because it's tricky. The key is the ## operator. If you were to throw this at the top of your code:
#define myexample(x,y,z) int example_##x##_##y##_##z## = x##y##z
then basically, what this does, is that during preprocessing, it will take any call to that macro, such as the following:
myexample(1,2,3);
and it will literally turn into
int example_1_2_3 = 123;
This allows you a ton of flexibility while coding if you use it correctly, but it doesn't exactly apply how you are trying to use it. With a little massaging, you could get it to work though.
One possible solution for your example might be:
#define H "Hello "
#define W "World!"
#define concat_and_print(a, b) cout << a << b << endl
and then do something like
concat_and_print(H,W);
From gcc online docs:
The '##' preprocessing operator performs token pasting. When a macro is expanded, the two tokens on either side of each '##' operator are combined into a single token, which then replaces the '##' and the two original tokens in the macro expansion.
Consider a C program that interprets named commands. There probably needs to be a table of commands, perhaps an array of structures declared as follows:
struct command
{
char *name;
void (*function) (void);
};
struct command commands[] =
{
{ "quit", quit_command },
{ "help", help_command },
...
};
It would be cleaner not to have to give each command name twice, once in the string constant and once in the function name. A macro which takes the name of a command as an argument can make this unnecessary. The string constant can be created with stringification, and the function name by concatenating the argument with _command. Here is how it is done:
#define COMMAND(NAME) { #NAME, NAME ## _command }
struct command commands[] =
{
COMMAND (quit),
COMMAND (help),
...
};
I just thought I would add an answer that cites the source as to why this works.
The C99 standard §5.1.1.2 defines translation phases for C code. Subsection 6 states:
Adjacent string literal tokens are concatenated.
Similarly, in the C++ standards (ISO 14882) §2.1 defines the Phases of translation. Here Subsection 6 states:
6 Adjacent ordinary string literal tokens are concatenated. Adjacent wide string literal tokens are concatenated.
This is why you can concatenate strings simply by placing them adjacent to one another:
printf("string"" one\n");
>> ./a.out
>> string one
The preprocessing part of the question is simply the usage of the #define preprocessing directive which does the substitution from identifier (H) to string ("Hello ").