Expand macro inside string literal
#define STRINGIFY2(X) #X
#define STRINGIFY(X) STRINGIFY2(X)
#define A 2
Then STRINGIFY(A)
will give you "2"
. You can concatenate it with other string literals by putting them side by side.
"I have the number " STRINGIFY(A) "."
gives you "I have the number 2."
.
Expand macros inside quoted string
You can't expand macros in strings, but you can write
#define COLOR "#00ff00"
f("abc "COLOR);
Remember that this concatenation is done by the C preprocessor, and is only a feature to concatenate plain strings, not variables or so.
C Macro should expand as char* in one place and wchar* in another place with L character
A quick and easy solution, with no extra macros:
- Use
MACRO_STRING
directly when you needchar *
. - Use
L"" MACRO_STRING
when you needwchar_t *
.
Expanding macro inside raw string
If you want to debug your crazy macros, you'd probably get more mileage out of directly examining the preprocessed output. Any C/C++ compiler will have an option for this. In GCC it's -E
; for MSVC, I don't recall where it is exactly, but one of the properties sections has "keep preprocessed output". When you do this, keep your #includes to a minimum, especially standard-library #includes; these can add hundreds or thousands of lines of code to the top of the preprocessed output.
Expand integer macro inside quoted string
The right way to do this is to use a *
in your format string, which will cause it to take the value from your argument list. For example:
printf("%.*s\n", 3, "abcde");
This is equivalent to:
printf("%.3s\n", "abcde");
That way you can use PATH_MAX
or any other value to control the format without having to worry about how they're defined (e.g., whether they contain parentheses or addition operators, etc.)
Do preprocessors expand macros surrounded by quotation marks?
Do common preprocessors like cpp and fpp expand macros surrounded by a
pair of quotation marks?
The C language specification describes the behavior of conforming C preprocessors. The actual standards for C are not freely available, but you can get copies of late drafts. For C18, for example, you could refer to N2176. In particular, you should have a look at sections 5.1.1.2 and 6.10.3. Of particular relevance is footnote 173 in section 6.10.3:
Since, by macro-replacement time, all character constants and string
literals are preprocessing tokens, not sequences possibly containing
identifier-like subsequences (see 5.1.1.2, translation phases), they
are never scanned for macro names or parameters.
(Substantially the same text appears in earlier versions of the standard, too.)
The bottom line for C, then, is that no, a conforming C preprocessor does not perform macro replacement on the contents of string literals or character constants.
The situation for Fortran is less clear cut, because the Fortran language specification does not define preprocessing facilities. There is an include
statement built in to the language itself, but Fortran practitioners generally would not consider its use to involve preprocessing. Fortran source code rarely relies on preprocessing features such as macro expansion or conditional compilation.
Some Fortran implementations nevertheless do provide a preprocessing facility, sometimes available as a standalone program named fpp
. You would need to consult the documentation of your specific fpp
for details, but generally these are adaptations of the C preprocessor to Fortran syntax. As such, no, I would not expect a Fortran preprocessor to perform macro expansion on the contents of character literals. I am not aware of any implementations that defy my expectations in that regard.
Expand X macro inside another macro
main.c:7:5: warning: implicit declaration of function ‘X’ [-Wimplicit-function-declaration]
Well, yes. At line 18, where macro STUFF
appears, it is first expanded to
TABLE
, then that is rescanned. TABLE
being defined as a macro, it, too, is expanded, resulting in
X("abc", "123", "ddd") X("def", "456", "aaa") X("ghi", "789", "ddd")
, then that is rescanned. But X
is not defined as a macro (or as anything else) at that point, because you previously undef
ined it. That leaves you with code that resembles three calls to an unknown function, without any kind of operator or separator between. It is invalid.
Your X macro has to be defined appropriately at the place where it is expanded. It does not need to be defined at all at the place where it appears in another macro's expansion text. You seem to have that backward.
As discussed in comments, the objective is to be able to define separate macros, for example STUFF
and STUFF2
that expand TABLE
to consistent results that differ from each other. This is as opposed to causing STUFF
to expand as wanted by manipulating the definition of X
.
This can be accomplished by changing the definition of TABLE
so that it is a function-like macro taking another macro name as an argument:
#define TABLE(m) \
m("abc", "123", "ddd") \
m("def", "456", "aaa") \
m("ghi", "789", "ddd")
The macros STUFF
and STUFF2
can then control the expansion by their choice of which macro name to pass to TABLE()
:
#define X(_a, _b, _c) _a
#define Y(_a, _b, _c) _b
#define STUFF TABLE(X)
#define STUFF2 TABLE(Y)
How to use Macro argument as string literal?
Use the preprocessor #
operator:
#define CALL_DO_SOMETHING(VAR) do_something(#VAR, VAR);
extract macro argument inside string
You probably need concat!()
for this. It would concatenate literals to yield a &'static str
:
macro_rules! update_user {
($tx:ident, $id:expr, $key:expr, $val:expr) => {
sqlx::query!(
concat!("UPDATE users SET $key = ", $key, " WHERE id = ", $id),
$val
).execute(&mut $tx).await?;
};
}
A similar example: Playground
Related Topics
Dealing with Floating Point Exceptions
Convert Shared Library to Static Library
Where Does the -Dndebug Normally Come From
C++ Conversion Operator for Converting to Function Pointer
Assert That Code Does Not Compile
Using Custom Camera in Opencv (Via Gstreamer)
Specialization of Member Function Template After Instantiation Error, and Order of Member Functions
How to Benchmark Boost Spirit Parser
How to Convert a Value from Host Byte Order to Little Endian
Why the Sequence-Operation Algorithms Predicates Are Passed by Copy
I++ Less Efficient Than ++I, How to Show This