I have two macros in my C code the helps me to compose the name of certain variables. As an example, consider the following:
#define MACROA(name) A_##name
#define MACROB(name) B_##name
void *MACROB(MACROA(object));
So, I'm trying to declare a variable called B_A_object. However, this doesn't work and the compiler throws me the message:
object.c:27:21: error: a parameter list without types is only allowed in a function definition
void *MACROB(MACROA(object));
^
object.c:26:26: note: expanded from macro 'MACROB'
#define MACROB(name) B_##name
^
So, it seems the preprocessor is not taking the result of MACROA(object), but it is considering the expression itself so that it tries to make B_MACROA(object). So, what do I have to do to make the preprocessor consider the result of a macro passed to another macro?
The concatenation operator acts weird. It concatenates first and evaluates later:
void *MACROB(MACROA(object)); // The original line
void *B_MACROA(object); // Becomes this, nothing more to expand
You can solve it this way:
#define CONC(a,b) a ## b
#define MACROA(name) CONC(A_, name)
#define MACROB(name) CONC(B_, name)
Related
Currently looking at some C code that doesn't make any sense to me. What is (elementSize)? How am supposed to pass arguments to this static function? What is the name of this syntax style so I can learn more abour it?
static int torch_Tensor_(elementSize)(lua_State *L)
{
luaT_pushinteger(L, THStorage_(elementSize)());
return 1;
}
https://github.com/torch/torch7/blob/master/generic/Tensor.c
This is the file I am trying to understand for reference.
Normally
static int torch_Tensor_(elementSize)(lua_State *L)
would mean torch_Tensor_ is a function that takes a single parameter called elementSize that has no type (?! - syntax error) and returns a function that takes a pointer to lua_State and returns an int. This is blatantly invalid (functions cannot return other functions).
But what's actually going on here is that torch_Tensor_ is defined as a function-like macro, so before the compiler even sees this declaration, torch_Tensor_(elementSize) is replaced by something else.
In https://github.com/torch/torch7/blob/master/Tensor.c there is
#include "general.h"
#define torch_Storage_(NAME) TH_CONCAT_4(torch_,Real,Storage_,NAME)
#define torch_Storage TH_CONCAT_STRING_3(torch.,Real,Storage)
#define torch_Tensor_(NAME) TH_CONCAT_4(torch_,Real,Tensor_,NAME)
#define torch_Tensor TH_CONCAT_STRING_3(torch.,Real,Tensor)
#include "generic/Tensor.c"
#include "THGenerateAllTypes.h"
#include "generic/Tensor.c"
#include "THGenerateHalfType.h"
with TH_CONCAT_... defined in lib/TH/THGeneral.h.in:
#define TH_CONCAT_STRING_3(x,y,z) TH_CONCAT_STRING_3_EXPAND(x,y,z)
#define TH_CONCAT_STRING_3_EXPAND(x,y,z) #x #y #z
#define TH_CONCAT_4_EXPAND(x,y,z,w) x ## y ## z ## w
#define TH_CONCAT_4(x,y,z,w) TH_CONCAT_4_EXPAND(x,y,z,w)
So torch_Tensor_ is defined as a macro before generic/Tensor.c is included.
torch_Tensor_(elementSize)
expands to
TH_CONCAT_4(torch_,Real,Tensor_,elementSize)
which expands to
TH_CONCAT_4_EXPAND(torch_,...,Tensor_,elementSize)
... is a placeholder, not real code. Real is defined as a macro in the various THGenerate*Type.h files, so this line actually becomes
TH_CONCAT_4_EXPAND(torch_,char,Tensor_,elementSize)
TH_CONCAT_4_EXPAND(torch_,int,Tensor_,elementSize)
TH_CONCAT_4_EXPAND(torch_,float,Tensor_,elementSize)
...
depending on context. Anyway, the end result is a single identifier of the form
torch_charTensor_elementSize
torch_intTensor_elementSize
torch_floatTensor_elementSize
...
(one token).
The resulting function definition thus looks like e.g.
static int torch_charTensor_elementSize(lua_State *L)
{
...
}
depending on which context generic/Tensor.c was included in.
The reason things are done this way is to have what amounts to the same code, but for multiple different types. In C++ you would write a function template:
namespace torch {
template<typename Real>
static int Tensor_elementSize(lua_State *L) { ... }
}
But C has no templates (nor namespaces), so the only way to get "generic" code like this is to do it manually with macros and preprocessing tricks (and manually "decorating" names; e.g. the elementSize function for floats is really called torch_floatTensor_elementSize).
All we're really trying to do is abstract over a type parameter, here called Real.
I have a macro that points to another macro:
#define USART1 ((USART_TypeDef *) USART1_BASE)
#define PIPE1 USART1
I'm trying to add a static text which I will use as a function definition (USART1 becomes USART1_IRQHandler). I tried something like:
#define _IRQ(NAME) NAME ## _IRQHandler
void _IRQ(PIPE1)(void) {
//...
}
but the name resolves as PIPE1_IRQHandler instead of USART1_IRQHandler. Then I tried #NAME to get the value of PIPE1, but it had fully resolved to the most low-level representation:
((USART_TypeDef *) ((((uint32_t)0x40000000) + 0x10000) + 0x3800))
Is there any way to get USART1_IRQHandler?
No, there isn't.
Macro arguments which participate in concatenation (##) and stringification (#) are not expanded at all in the course of replacing the macro with its definition. Consequently, it is common to pass arguments through an indirect macro so that they will be expanded fully befire being passed to the macro which concatenates or stringifies them.
There is no mechanism for partial expansion. It's basically all or nothing.
If you want to build up complicated chains of macro substitution, you need to avoid using words both as macros and as token pieces, as in your example.
I want to embed a preprocessor directive into a function name. Basically I want to make a macro that takes a preprocessor define as argument and concatenates it's defined VALUE to get a function name.
Basically this:
#define PREFIX foo
#define CALL(P, x) _##P_bar(x)
...then
CALL(PREFIX, x) should become _foo_bar(x)
Unfortunately this results in _P_bar instead of _foo_bar.
Is it possible to make it work as above?
The C standard defines special behavior for macro parameters immediately preceded and followed by ## operator. In such case they are not fully expanded. This is why your code did not behave as you expected. To further expand a parameter, you have to use it in a way that it is not immediately preceded or followed by ## operator. Try the following:
#define PREFIX foo
#define CALL2(P,x) _##P##_bar(x)
#define CALL(P, x) CALL2(P,x)
CALL(PREFIX, x)
I'm trying to pass a comma through multiple levels of macros, but the preprocessor doesn't like that...
// This is just simplified, in reality I have some other variadic function which will
// stop upon encountering the -1 and APPEND_COMMA() may add more args (like `a, b,`)
#include <stdio.h>
#define MACRO_EX(val) printf("%d %d", val -1);
#define MACRO(val) MACRO_EX(val)
#define APPEND_COMMA(a) a,
int main() {
MACRO(APPEND_COMMA(1));
return 0;
}
What exactly is causing the compile failure here?
test.c:10:8: error: too many arguments provided to function-like macro invocation
MACRO(APPEND_COMMA(1));
^
test.c:7:26: note: expanded from macro 'APPEND_COMMA'
#define APPEND_COMMA(a) a,
^
test.c:5:29: note: expanded from macro 'MACRO'
#define MACRO(val) MACRO_EX(val)
^
test.c:3:9: note: macro 'MACRO_EX' defined here
#define MACRO_EX(val) printf("%d %d", val 0);
^
test.c:10:2: error: use of undeclared identifier 'MACRO_EX'
MACRO(APPEND_COMMA(1));
^
test.c:5:20: note: expanded from macro 'MACRO'
#define MACRO(val) MACRO_EX(val)
^
2 errors generated.
The comma seems to be expanded in the called macro, so that MACRO_EX(a,) is called, which is not what I want.
I found some workaround for this by using __VA_ARGS__:
#define MACRO_EX(...) printf("%d %d", __VA_ARGS__ -1);
But I'd really prefer to pass the comma cleanly through all the macros up to the variadic function call and use cleanly named macro parameters [like I intended in my original code].
Is there any way to achieve that?
The only way to guarantee a comma will be passed "cleanly" through macro parameters is to wrap it in parentheses:
#define APPEND_COMMA(a) (a,)
Now the result of APPEND_COMMA will always be a single preprocessor argument.
The obvious problem with this is that it produces printf("%d %d", (1,) -1);, which is now valid preprocessor code, but no longer valid C code. This is rectified by inserting an "unpack" step into the definition of MACRO_EX:
#define IDENTITY(...) __VA_ARGS__
#define MACRO_EX(val) printf("%d %d", IDENTITY val -1);
IDENTITY will unpack the contents of val, assuming val is a parenthesised argument list, during MACRO_EX's rescan step.
What about situations where val might not be parenthesised, because it doesn't contain a comma? The answer is to not let them arise. Arguments that might contain a comma should always be wrapped, so they can always be safely unwrapped at the final point of insertion. Macros need to be designed with the knowledge of whether they anticipate single tokens or lists*. This is the preprocessor's equivalent of a static type constraint: macros like MACRO require an argument of type list, not of type atom (and the calling macros similarly need to be written with the correct type signatures in mind); on those occasions when they need a single argument only, pass them a single-element list.
* It is technically possible to design a macro that tests whether its argument is parenthesised and branches on the result, but you're getting into dark magic territory there. Stick to fixed types for clarity.
I'm trying to create a Macro function for defining function pointers , functions etc.
Here's what I'm trying to do:
#define PRO_SIGNAL_MAX 5
#define PRO_SIGNAL( func, param ) (*func [ PRO_SIGNAL_MAX ])(param)
I want to use this to declare an array of function pointers of size PRO_SIGNAL_MAX.
So, when I use this here:
void PRO_SIGNAL( paint, (Pro_Window*) );
I want it to generate:
void (*paint [ 5 ])(Pro_Window*) ;
but it isn't working quite as I planned, I get this error:
pro_window.c|16|error: expected declaration specifiers or '...' before '(' token|
What exactly is the problem?
Omit the parentheses around Pro_Window*:
void PRO_SIGNAL(paint, Pro_Window*);
Macro parameters are substituted literally, so you ended up with:
void (*paint[PRO_SIGNAL_MAX])((Pro_Window*));
which is a syntax error.
Also, it is a good practice to enclose macro parameters in parentheses in the macro itself, since you never know whether the caller will pass an expression or a single token:
#define PRO_SIGNAL(func, param) (*(func)[PRO_SIGNAL_MAX])(param)
Its the (Pro_Window*) part. Your PRO_SIGNAL( paint, (Pro_Window*) ) will expand to
(*paint [ PRO_SIGNAL_MAX ])((Pro_Window*))
I suppose the compile is not happy about the nested parenthesis.
When baffled by macro expansion, it's often good to look at what the preprocessor actually fed the compiler. How to generate the preprocessed code varies with compilers, though.