I want to stringify the result of a macro expansion.
I've tried with the following:
#define QUOTE(str) #str
#define TEST thisisatest
#define TESTE QUOTE(TEST)
And TESTE gets expanded to: "TEST", while I'm trying to get "thisisatest". I know this is the correct behavior of the preprocessor but can anyone help me with a way to achieve the other one?
Using TESTE #TEST is not valid
Using TESTE QUOTE(thisisatest) is not what I'm trying to do
Like this:
#include <stdio.h>
#define QUOTE(str) #str
#define EXPAND_AND_QUOTE(str) QUOTE(str)
#define TEST thisisatest
#define TESTE EXPAND_AND_QUOTE(TEST)
int main() {
printf(TESTE);
}
The reason is that when macro arguments are substituted into the macro body, they are expanded unless they appear with the # or ## preprocessor operators in that macro. So, str (with value TEST in your code) isn't expanded in QUOTE, but it is expanded in EXPAND_AND_QUOTE.
To clarify a bit more, essentially the preprocessor was made to execute another "stage". i.e :
1st case:
->TESTE
->QUOTE(TEST) # preprocessor encounters QUOTE
# first so it expands it *without expanding its argument*
# as the '#' symbol is used
->TEST
2nd case:
->TESTE
->EXPAND_AND_QUOTE(TEST)
->QUOTE(thisisatest)
# after expanding EXPAND_AND_QUOTE
# in the previous line
# the preprocessor checked for more macros
# to expand, it found TEST and expanded it
# to 'thisisatest'
->thisisatest
Related
I'm trying to concatenate a macro call with a token to create a new one, for instance:
#define TEST(X) X ## _TEST
#define CONCAT(X) TEST(X) ## _CONCAT
CONCAT(OK);
Then I check the output with gcc -E; I would want to get OK_TEST_CONCAT; but instead I get an error:
error: pasting ")" and "_CONCAT" does not give a valid preprocessing token
If I remove ## I get no error but the output is OK_TEST _CONCAT;
This is a minimal example, so the easiest here would be to combine everything in a single macro, but know that it's impossible for me to get rid of the first call to TEST. Is there a way to remove that space?
Thanks
EDIT:
Ok so from the confusion maybe my example was a little too minimal, that's my fault. Here is a more plausible use case:
I want all the prototypes in a certain header to be prefixed by the PREFIX defined in that header.
proto.h:
#define EXPAND(X) EXPAND_HELPER(X)
#define EXPAND_HELPER(X) X
#define PROTO(NAME) PREFIX ## NAME
other.h:
#include <proto.h>
#define PREFIX other
int PROTO(test)(int a, int b);
...
What I want is all the prototypes in other.h to have this form: int other_test(int a, int b);. But as it is they have this form: int PREFIX_test(int a, int b);. After googling I found that I needed to force PREFIX to rescan, so I tried this:
#define PROTO(NAME) EXPAND(PREFIX) ## NAME
which prompted my question. Now if I look at #Lundin's answer, I can adapt it to give what I want:
Solution:
#define PROTO(NAME) PROTO_HELPER(PREFIX, NAME)
#define PROTO_HELPER(PREFIX, NAME) PROTO_EXPAND(PREFIX, NAME)
#define PROTO_EXPAND(PREFIX, NAME) PREFIX ## NAME
Thanks!
All preprocessor tokens must be expanded before a function-like macro using ## or # is called. Because ## or # is applied before macro expansion. In your case TEST(X) only expands X into TEST(OK) and then the preprocessor attempts to paste TEST(OK) with _CONCAT which won't work. For each attempt to concatenate tokens, you must first expand all macros before ##, which is done by extra helper macros that force a rescanning/replacement.
The contrived solution given #define TEST(X) X ## _TEST would be this:
#define CONCAT(X) EXPAND_HELPER(TEST(X)) // expands TEST(X) to TEST(OK)
-->
#define EXPAND_HELPER(X) CONCAT_HELPER(X, _CONCAT) // expands TEST(OK) to OK_TEST
-->
#define CONCAT_HELPER(X,Y) X ## Y
That is:
// NOTE: contrived solution, avoid
#define TEST(X) X ## _TEST
#define CONCAT_HELPER(X,Y) X ## Y
#define EXPAND_HELPER(X) CONCAT_HELPER(X, _CONCAT)
#define CONCAT(X) EXPAND_HELPER(TEST(X))
...
int CONCAT(OK) = 1; // becomes int OK_TEST_CONCAT = 1;
A much simpler solution would be:
#define CONCAT(X) X ## _TEST ## _CONCAT
I have these definitions in a project_conf.h file
#define MCU 16F628
#define MCU_HEADER_FILE MCU##.h
And I want to implement a macro that would substitute this line
#include <MCU_HEADER_FILE>
with just
CALL_MUC_HEADER_FILE
These <> things I dont know how to handle.
Apart that you can't effectively define macro, that contains #include directive, that is something like:
#define FOO #include <foo.h>
there is another issue with these macro definitions:
#define MCU 16F628
#define MCU_HEADER_FILE MCU##.h
The second object-like macro is invalid, since it does not produce valid preprocessing token. The ## operator concatenates token MCU (not even expanding it) with ., which combines into MCU., invoking an undefined behavior.
Regarding to C11 (N1570) ยง6.10.3.3/p3 The ## operator:
If the result is not a valid preprocessing token, the behavior is
undefined.
For instance, GCC compiler has diagnostic message in such case, when you run it with -E flag:
check.c:7:1: error: pasting "MCU" and "." does not give a valid
preprocessing token
You can also see from here, that MCU was not expanded into its text replacement.
The valid solution would be to get rid off ## operator at all and apply third, less-known form of #include directive:
# include pp-tokens new-line
Here is one possible way:
#define MCU_HEADER <MCU.h> // MCU will be expanded into 16F628
#include MCU_HEADER
But as stated above it best what you can do with #define directive as is.
It looks that you are thinking too complicated.
The tokens after an #include directive are simply expanded, you don't need to do any macro concatenation magic with it:
#define incFile(A) A.h
#define hoho(X) <incFile(X)>
#include hoho(string)
Note: the MCU_HEADER_FILE definition should be changed to include the < and > on either side
#define GLUE_IMPL(A, B) A##B
#define GLUE(A, B) GLUE_IMPL(A, B)
#define MCU 16F628
#define MCU_HEADER_FILE GLUE(GLUE(GLUE(<, MCU),.h), >)
#include MCU_HEADER_FILE
You can't put anything in a #define statement that begins with a # (#include, #if, #endif e.t.c.), so #include MCU_HEADER_FILE is the best you can get.
I have concrete_impl.h (as is):
#ifdef TUPLE_ITERATOR_WITH_INDEX
#define TUPLE_ITERATOR TUPLE_ITERATOR_NO_INDEX
#define iterate_tuple_fname iterate_tuple_id
#else
#define TUPLE_ITERATOR TUPLE_ITERATOR_INDEX
#define iterate_tuple_fname iterate_tuple
#endif
#undef iterate_tuple_fname_back
#define iterate_tuple_fname_back iterate_tuple_fname##_back
static void iterate_tuple_fname() // ok
{
}
static void iterate_tuple_fname_back() // redefinition error
{
}
And concrete.h (as is):
#ifndef CONCRETE_H
#define CONCRETE_H
#define TUPLE_ITERATOR_WITH_INDEX
#include "concrete_impl.h"
#undef TUPLE_ITERATOR_WITH_INDEX
#include "concrete_impl.h"
#endif // CONCRETE_H
What I want to get - is 4 functions:
iterate_tuple
iterate_tuple_id
iterate_tuple_back
iterate_tuple_id_back
But on "_back" functions I have redefinition error. Why?
iterate_tuple_fname##_back is nothing else than iterate_tuple_fname_back. To have iterate_tuple_fname replaced by its macro replacement list, you'll need a helper macro:
#define CONCAT(a, b) a ## b
#define iterate_tuple_fname_back CONCAT(iterate_tuple_fname, _back)
UPDATE: Sorry, have forgotten all about C after several years of C# programming.
It actually needs double run through helper macros:
#define CONCAT1(a, b) a ## b
#define CONCAT(a, b) CONCAT1(a, b)
#define iterate_tuple_fname_back CONCAT(iterate_tuple_fname, _back)
Apparently you misunderstand how the ## operator works.
If the preprocessing token adjacent to the ## operator is a parameter of the current macro, then this parameter is recursively analyzed for further replacement first, and the result of that replacement substituted into the result.
If the preprocessing token adjacent to the ## operator is not a parameter of the current macro, then recursive analysis and replacement of that token does not take place. The token is simply concatenated with the other token.
Later, once all parameters are substituted and all concatenations are joined, the entire result is rescanned again for further replacements. But then it is already be too late for your example.
In your case you defined this macro
#define iterate_tuple_fname_back iterate_tuple_fname##_back
Since iterate_tuple_fname is not a parameter of this macro, no early replacement occurs for iterate_tuple_fname. The whole thing is immediately concatenated into iterate_tuple_fname_back and only after that it is rescanned. But rescan finds nothing to replace there, so iterate_tuple_fname_back is the final result.
If you want the preprocessor to replace the left-hand side of the ## operator (which was your intent apparently), you absolutely have to use a macro parameter on the left-hand side, as in
#define ITF_back(prefix) prefix##_back
and then you can use this macro as
ITF_back(iterate_tuple_fname)
Now the rescan and recursive replacement inside iterate_tuple_fname will occur early, before the concatenation with the _back part. I.e. it will work as you wanted it to.
This question already has answers here:
The ## operator in C
(7 answers)
Closed 4 years ago.
something like #NAME or ##NAME. what do they mean in C? I saw them in GCC documents about macro.
operator ## concatenates two arguments leaving no blank spaces between them..
#define printe(a,b) a ## b
printe(c,out) << "testing";
output is : testing
and single # is used for parameter replacement withe the string parameter
like
#define st(x) #x
cout<<st(tesing); // equivalent to cout<<"testing";
and # is also a preprocessor directive..
A code statement beginning with # indicates what follows is a preprocessor directive and should be expanded by the pre-processor.
## is called token Pasting or Token concatenation macro.
From the wikipedia page describing the C preprocessor:
The ## operator concatenates two tokens into one token, as in this example:
#define DECLARE_STRUCT_TYPE(name) typedef struct name##_s name##_t
DECLARE_STRUCT_TYPE(g_object); // Outputs typedef struct g_object_s g_object_t;
The # operator signals other directives to the C preprocessor, for example: #include, #define, #undef, #error, #if, #ifdef, #ifndef, #else, #elif, #endif
The '#' is really not an operator, they are preprocessor directives, and the '##' is used only for function macro definitions.
There are many preprocessor directives in C:
For Macro Definitions there are:
#define
#undef
For Conditional Inclusions, there are:
#ifdef
#ifndef
#if
#endif
#else
#elif
For Line Control, there is:
#line
For Error, there is:
#error
For Source file inclusion, there is:
#include
For Pragma directive, there is:
#pragma
For more information, read this http://www.cplusplus.com/doc/tutorial/preprocessor/
I'm trying to figure out how to build a variable string for the #include statement using GCC.
The idea is that for each source module I have written, I want to include as a header, a dynamically generated C source, that was created earlier in the build process.
Generating this file is not an issue. Including it, unfortunately, is.
What I have so far is (identities.h):
// identities.h
# define PASTER2(str) #str
# define PASTER(str) PASTER2(str ## .iden)
# define EVALUATOR(x) PASTER(x)
# define IDENTITIES_FILE EVALUATOR(__FILE__)
# include IDENTITIES_FILE
Ideally, this would be used like so (main.c):
//main.c
# include "identities.h"
int main() {return 0;}
Which would be expanded in a single pass by the preprocessor before compilation to yield:
//main.c (preprocessed)
# include "main.c.iden"
int main() {return 0;}
The two levels of indirection I'm using (PASTER and EVALUATOR) are a result of this post.
Unfortunately, this is not working and I am left with the error:
obj/win32/dbg/main.o
In file included from main.c:1:0:
identities.h:42:1: error: #include expects "FILENAME" or <FILENAME>
I think the problem is that the include statement is missing quotes.. Any ideas?
This is actually done in the Linux source tree; See line 100 of compiler-gcc.h.
#define __gcc_header(x) #x
#define _gcc_header(x) __gcc_header(linux/compiler-gcc##x.h)
#define gcc_header(x) _gcc_header(x)
#include gcc_header(__GNUC__)
I'm trying to figure out how to build a variable string for the #include statement using GCC.
This token pastes the value of __GNUC__ to a string; "linux/compiler-gcc" __GNUC__ ".h" and then stringifies the result. This maybe a gcc pre-processor extension.
Here is an example,
t1.h
#define FOO 10
t2.h
#define FOO 20
a.c
#ifndef VERSION
#define VERSION 1
#endif
#define __gcc_header(x) #x
#define _gcc_header(x) __gcc_header(t##x.h)
#define gcc_header(x) _gcc_header(x)
#include gcc_header(VERSION)
#include <stdio.h>
int main(void)
{
printf("FOO is %d\n", FOO);
return 0;
}
Here are two compiles,
g++ -o a a.cc
g++ -DVERSION=2 -o a a.cc
The output of either compile gives expected result.
As with the Linux source, you can key off of gcc pre-defined values. echo | g++ -dM -E - will give a list.
For your case, you can use the makefile to pass a define to the compile to allow dynamic inclusion of the generated header without altering the source. But then a simple alternative is just to run sed, etc on a template source file and replace it with the known include name.
Either technique is good for generating test fixtures, etc. However, for compiler feature discovery, this is a better method. For programmers who use IDEs, this might be their only choice.
I am fairly certain you can't do what you want, __FILE__ returns a string and ## works on tokens and there is no CPP string concat preprocessor macro. Normally this is gotten around due to the fact that two strings in succession e.g.
"Hello" " World"
will be treated as a single string by the C++ parser. However, #include is part of the preprocessor, and thus cannot take advantage of that fact.
Old answer:
Why are you doing this
{ #str, str ## .iden }
I'm certain that's not preprocessor syntax; what do you hope to achieve via that? Have you tried just:
str ## .iden
A '{' could explain the error you are getting.
What about BOOST_PP_STRINGIZE from the Boost Preprocessor library . It is specifically made to add quotes around a name.
Skipping the whole inclusion syntax thing for a while, I don't understand what your code is trying to do. You say:
# define PASTER(str) { #str, str ## .iden }
You give it main.c and expect "main.c.iden", but that returns {"main.c", main.c.iden }.
Are instead you looking for this?
#define PASTER2(str) #str
#define PASTER(str) PASTER2(str ## .iden)
You cannot use preprocessor like this. You have to supply a filename to the #include directive, it can't be some other macro.