How to fix the macro expansion issue below ?
#define GET_VAL 3,2
#define ADD_VAL(val0, val1) ((val0) + (val1))
void foo()
{
int res = ADD_VAL(GET_VAL);
}
The macro is getting expanded as below and resulting in an error. I am using MSVC 2019
res = 3,2 + ;
I even tried using a helper macro as below, but still getting the same error.
#define GET_VAL 3,2
#define ADD_VAL1(val0, val1) (val0 + val1)
#define ADD_VAL(val) ADD_VAL1(val)
Expecting expansion:
ADD_VAL(GET_VAL); --> ADD_VAL(3, 2); --> 3 + 2
By default msvc doesn't use a standard confirming preprocessor implementation, make sure to enable it with /Zc:preprocessor
Macros fully expand their arguments in isolation before pasting them into the replacement text, but the resulting tokens aren't separated into a new argument list. They way to fix your behavior is to create an intermediate macro that expands the arguments, and passes the expanded arguments to your macro:
#define GET_VAL 1,2
#define ADD_VAL(...) ADD_VAL_(__VA_ARGS__)
#define ADD_VAL_(a,b) ((a)+(b))
ADD_VAL(GET_VAL) // should work now
Another option is to write a fx macro that evaluates arguments and applies a function to them:
#define FX(f,...) f(__VA_ARGS__)
#define ADD_VAL(a,b) ((a)+(b))
FX(ADD_VAL,GET_VAL) // should work now
C preprocessor can be abused in horrible ways
#define GET_VAL 3,2
// #define ADD_VAL(val0, val1) ((val0) + (val1))
#define ADD_VAL(val) ((int [2]){val}[0] + (int [2]){val}[1])
int main() {
printf("%d\n",ADD_VAL(GET_VAL));
}
Output
5
Related
I'm able to follow the code path up to a certain point. Briefly:
The program accepts an ASCII hexadecimal string and converts it to binary. https://github.com/BrianGladman/aes/blob/master/aesxam.c#L366-L382
If arg[3] is an “E”, it defines an aes_encrypt_ctx struct and passes the key, the calculated key_len value, and the aes_encrypt_ctx stuct to aes_encrypt_key. https://github.com/BrianGladman/aes/blob/master/aesxam.c#L409-L412
aes_encrypt_key is defined in aeskey.c. Depending on key_len, the function aes_encrypt_key<NNN> is called. They key and the struct are passed to the function. https://github.com/BrianGladman/aes/blob/master/aeskey.c#L545-L547
But where is the aes_encrypt_key128 function?
This line appears to be my huckleberry:
# define aes_xi(x) aes_ ## x
So hopefully I'm onto something. It's mapping aes_encrypt_key128 to aes_xi(encrypt_key128), right?
AES_RETURN aes_xi(encrypt_key128)(const unsigned char *key, aes_encrypt_ctx cx[1])
{ uint32_t ss[4];
cx->ks[0] = ss[0] = word_in(key, 0);
cx->ks[1] = ss[1] = word_in(key, 1);
cx->ks[2] = ss[2] = word_in(key, 2);
cx->ks[3] = ss[3] = word_in(key, 3);
#ifdef ENC_KS_UNROLL
ke4(cx->ks, 0); ke4(cx->ks, 1);
ke4(cx->ks, 2); ke4(cx->ks, 3);
ke4(cx->ks, 4); ke4(cx->ks, 5);
ke4(cx->ks, 6); ke4(cx->ks, 7);
ke4(cx->ks, 8);
#else
{ uint32_t i;
for(i = 0; i < 9; ++i)
ke4(cx->ks, i);
}
#endif
ke4(cx->ks, 9);
cx->inf.l = 0;
cx->inf.b[0] = 10 * AES_BLOCK_SIZE;
#ifdef USE_VIA_ACE_IF_PRESENT
if(VIA_ACE_AVAILABLE)
cx->inf.b[1] = 0xff;
#endif
MARK_AS_ENCRYPTION_CTX(cx);
return EXIT_SUCCESS;
}
I see some pattern replacement happening here. I guess at this point I was wondering if you could point me to the docs that explain this feature of #define?
Here are some docs which explain token concatenation. You can also take this as a suggestion about where to search systematically for reliable docs:
The C standard. At this website you can download WG14 N1570, which is quite similar to the C11 standard (it's a pre-standard draft, but it's basically the same as the standard except you don't have to pay for it.) There's an HTML version of this document at http://port70.net/~nsz/c/c11/n1570.html, which is handy for constructing links. With that in mind, I can point you at the actual standard definition of ## in §6.10.3.3 of the standard.
The C standard can be a bit rough going if you're not already an expert in C. It makes very few concessions for learners. A more readable document is Gnu GCC's C Preprocessor (CPP) manual, although it is does not always distinguish between standard features and GCC extensions. Still, it's quite readable and there's lots of useful information. The ## operator is explained in Chapter 3.5
cppreference.com is better known as a C++ reference site, but it also contains documentation about C. It's language is almost as telegraphic as the C++/C standards, and it is not always 100% accurate (although it is very good), but it has several advantages. For one thing, it combines documentation for different standard versions, so it is really useful for knowing when a feature entered the language (and consequently which compiler version you will need to use the feature). Also, it is well cross-linked, so it's very easy to navigate. Here's what it has to say about the preprocessor; you'll find documentation about ## here.
I've been at this a while but it started to become clear to me that there is pattern matching going on in the pre-processing macros of the aeskey.c file. The only doc I've been able to find is this one.
Pattern Matching
The ## operator is used to concatenate two tokens into one token. This
is provides a very powerful way to do pattern matching. Say we want to
write a IIF macro, we could write it like this:
#define IIF(cond) IIF_ ## cond
#define IIF_0(t, f) f
#define IIF_1(t, f) t
However there is one problem with this approach. A subtle side effect
of the ## operator is that it inhibits expansion. Heres an example:
#define A() 1
//This correctly expands to true
IIF(1)(true, false)
// This will however expand to
IIF_A()(true, false)
// This is because A() doesn't expand to 1,
// because its inhibited by the ## operator
IIF(A())(true, false)
The way to work around this is to use another indirection. Since this
is commonly done we can write a macro called CAT that will concatenate
without inhibition.
#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
So now we can write the IIF macro (its called IIF right now, later we
will show how to define a more generalized way of defining an IF
macro):
#define IIF(c) PRIMITIVE_CAT(IIF_, c)
#define IIF_0(t, ...) __VA_ARGS__
#define IIF_1(t, ...) t
#define A() 1
//This correctly expands to true
IIF(1)(true, false)
// And this will also now correctly expand to true
IIF(A())(true, false)
With pattern matching we can define other operations, such as COMPL
which takes the complement:
#define COMPL(b) PRIMITIVE_CAT(COMPL_, b)
#define COMPL_0 1
#define COMPL_1 0
or BITAND:
#define BITAND(x) PRIMITIVE_CAT(BITAND_, x)
#define BITAND_0(y) 0
#define BITAND_1(y) y
We can define increment and decrement operators as macros:
#define INC(x) PRIMITIVE_CAT(INC_, x)
#define INC_0 1
#define INC_1 2
#define INC_2 3
#define INC_3 4
#define INC_4 5
#define INC_5 6
#define INC_6 7
#define INC_7 8
#define INC_8 9
#define INC_9 9
#define DEC(x) PRIMITIVE_CAT(DEC_, x)
#define DEC_0 0
#define DEC_1 0
#define DEC_2 1
#define DEC_3 2
#define DEC_4 3
#define DEC_5 4
#define DEC_6 5
#define DEC_7 6
#define DEC_8 7
#define DEC_9 8
Background
In a separate question of mine, I created a function-like-macro that allows me to concatenate a user-supplied text literal to create a macro name, i.e.:
/******************************************************************************
* coconut.h
******************************************************************************/
#define COCONUT_FX_REGISTER (100)
#define COCONUT_BASE_REGISTER (101)
/*******************************************************************************
* pineapple.h
******************************************************************************/
#define PINEAPPLE_FX_REGISTER (200)
#define PINEAPPLE_BASE_REGISTER (201)
/*******************************************************************************
* test.c.
******************************************************************************/
#include <stdio.h>
#include "translation.h"
#include "coconut.h"
#include "pineapple.h"
int main(void) {
int i = getTranslation(FX_REGISTER, COCONUT);
printf("Translation:%d.\n", i);
return 0;
}
/*******************************************************************************
* translation.h
******************************************************************************/
#define getTranslation(x, y) y ## _ ## x
Goal
I would like to extend this logic so that I can use a macro for a default value to pass to getTranslation, i.e.:
#define XFRM(x) #x
#define XFRM2(x) XFRM(x)
#define DEFAULT_PRODUCT XFRM2(COCONUT)
int main(void) {
int i = getTranslation(FX_REGISTER, DEFAULT_PRODUCT);
printf("Translation:%d.\n", i);
return 0;
}
Problem
However, I can't seem to get DEFAULT_PRODUCT to be converted to a non-string text literal.
Build Errors
main.c: In function ‘main’:
main.c:14:35: error: ‘DEFAULT_PRODUCT_FX_REGISTER’ undeclared (first use in this function)
printf("%d\n", getTranslation(FX_REGISTER, DEFAULT_PRODUCT));
^
translation.h:33:25: note: in definition of macro ‘getTranslation’
#define getTranslation(x, y) y ## _ ## x
^
main.c:14:35: note: each undeclared identifier is reported only once for each function it appears in
printf("%d\n", getTranslation(FX_REGISTER, DEFAULT_PRODUCT));
^
translation.h:33:25: note: in definition of macro ‘getTranslation’
#define getTranslation(x, y) y ## _ ## x
Question
How can I create a DEFAULT_PRODUCT macro that resolves to a non-string text literal so that I can create a "default" value to use with getTranslation? This is using GCC set to C99 pedantic.
Sounds like an XY problem.
It seems that macro concatenations are processed simultaneous to macro literal expansions, so I'm afraid there's no way to create a DEFAULT_PRODUCT macro that gets expanded before getTranslation.
My proposal: Create another macro function getDefaultTranslation(x) and you'll easily achieve what you want.
// You may want to add appropriate comments
// so code reviewers know what this is doing.
#define getDefaultTranslation(x) COCONUT ## x
Regarding this question, macro expansion is done layer-by-layer, and at the same layer concatenation has a higher precedence , so adding another layer should work. See ringø's answer below.
You need to add an indirection in order to let the preprocessor expand the macros before doing the concatenation
#define CONCAT(a, b) a ## _ ## b
#define getTranslation(x, y) CONCAT(x,y)
#define XFRM(x) x
#define XFRM2(x) XFRM(x)
#define DEFAULT_PRODUCT XFRM2(COCONUT)
Note that XFRM has its # removed (off x), otherwise the " gives an invalid preprocessing token.
This way you get
int i = FX_REGISTER_COCONUT;
#define V_M1 10
#define A_M1 60
#define V_M2 15
#define A_M2 56
#define M1 { V_M1, A_M1 }
#define M2 { V_M2, A_M2 }
int m1[]=M1, m2[]=M2;
Is there a way to simplify the definition of the M1 and M2 macros so that I don't have to repeat their names inside (source of errors in my case due to the actual complexity of the macros) ? Something like:
#define M1 { V_MyOwnName, A_MyOwnName }
#define M2 { V_MyOwnName, A_MyOwnName }
Add a level of indirection with a function-like macro
#define EXPAND(name) { V_##name, A_##name }
#define M1 EXPAND(M1)
#define M2 EXPAND(M2)
The ## is the token concatenation operator, that takes V and whatever you pass as name and glues them to form a single token. If the result is another macro, it's expanded further.
Macros like these are often questionable practice. Consider grouping your values in const structs or similar, for better program design.
That being said, everything in C is possible if you throw enough evil macros on it. Given no other choice but to use macros, I would do something like this:
#define M(n) { V_M ## n, A_M##n }
int m1[]=M(1), m2[]=M(2);
I am having trouble getting this macro expanison right
#define foo Hello
#ifdef foo
#define wrapper(x) foo ## x
#else
#define wrapper(x) boo ## x
#endif
calling:
wrapper(_world)
I would like the result of
Hello_world
however, the macro is treating the "foo" define as a literal, and thus giving
foo_world
Can someone point out my mistake?
Thanks
I would recommend gnu-cpp-manual which clearly explains how macros are expanded.
Macro arguments are completely macro-expanded before they are substituted into a macro body, unless they(macro arguments) are stringified or pasted with other tokens (by the macro function that is directly applied to).
For example:
If an argument is stringified or concatenated, the prescan does not occur.
#define AFTERX(x) X_ ## x
#define XAFTERX(x) AFTERX(x)
#define TABLESIZE 1024
#define BUFSIZE TABLESIZE
AFTERX(BUFSIZE) => X_BUFSIZE: since AFTERX is to concatenate argument with prefix, its argument is not expanded, remaining BUFSIZE.
XAFTERX(BUFSIZE) => X_1024: XAFTERX does not do concatenation directly, so BUFSIZE will be expanded first.
Generally, arguments are scanned twice to expand macro called in them.
--- edit ---
So the better practice is: (code from QEMU source)
#ifndef glue
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
#define stringify(s) tostring(s)
#define tostring(s) #s
#endif
glue(x,y) will concatenate x and y with both already expanded.
The following (test with gcc -E blah.c):
#define UNUSED(type) type UNUSED_ ## __COUNTER__
UNUSED(char const *)
UNUSED(int)
Generates:
char const * UNUSED__COUNTER__
int UNUSED__COUNTER__
I'm expecting:
char const * UNUSED0
int UNUSED1
I've tried calling another macro, wrapping the arguments in brackets to no avail.
If I don't paste the tokens it seems to work fine.
The documentation specifically mentions the use of __COUNTER__ in token pasting.
What am I doing wrong?
Experimenting with gcc 4.4, this works:
#define UNUSED(type) UNUSED_(type, __COUNTER__)
#define UNUSED_(type, counter) UNUSED__(type, counter)
#define UNUSED__(type, counter) type UNUSED_ ## counter
UNUSED(char const *)
UNUSED(int)
But it doesn't work if I take out even one level of intermediates.
__COUNTER__ was only introduced in GCC 4.3 - if you happen to use an earlier version, the macro is simply not defined. In that case Boost.PPs BOOST_PP_COUNTER macro might be worth looking into.
On newer GCC versions you still need a different approach to concatenation, as ## prevents its arguments from expanding. Thus you have to expand them first before using ##:
#define CAT(a, b) CAT_I(a, b)
#define CAT_I(a, b) CAT_II(a ## b)
#define CAT_II(x) x
#define UNUSED(type) type CAT(UNUSED_, __COUNTER__)
If you're already using Boost, BOOST_PP_CAT() gives you the same functionality.
I believe you must "double expand" it:
#define STR(x) #x
#define UNUSED(type) type UNUSED_ ## STR(__COUNTER__)
UNUSED(char const *)
UNUSED(int)