Reputation: 1325
I have something like, where I try to use macro expansion with a calculation resulting into a string of chars using C:
#define S_O(N, X1, Y1, X2, Y2, RI, GI, BI, RO, GO, BO) \
"S" #N*2-1 "H;" \
"S" #N*2-1 "Z;" \
"S" #N*2-1 "M2;" \
"S" #N*2-1 "PA" #X1 "," #Y1 ";" \
"S" #N*2-1 "PB" #X2 "," #Y2 ";" \
"S" #N*2-1 "W2,2;" \
"S" #N*2-1 "R" #RO ";" \
"S" #N*2-1 "G" #GO ";" \
"S" #N*2-1 "B" #BO ";" \
"S" #N*2-1 "A0;" \
"S" #N*2-1 "BD0;" \
"S" #N*2-1 "S;" \
"S" #N*2-1 "S;" \
"S" #N*2 "H;" \
"S" #N*2 "Z;" \
"S" #N*2 "M2;" \
"S" #N*2 "PA" #X1 "," #Y1 ";" \
"S" #N*2 "PB" #X2 "," #Y2 ";" \
"S" #N*2 "W2,2;" \
"S" #N*2 "R" #RI ";" \
"S" #N*2 "G" #GI ";" \
"S" #N*2 "B" #BI ";" \
"S" #N*2 "A0;" \
"S" #N*2 "BD0;" \
"S" #N*2 "S;" \
"S" #N*2 "S;"
/* later in the code is used like this: */
char buffer[1024]={0};
snprintf(1024, S_O(1, 10, 20, 1880, 1060, 0, 0, 0, 255, 255, 255));
/* the output should be:
* "S1H;S1Z;" etc.
*/
Obviously, this doesn't compile... How may I achieve my goal to avoid a function encapsulating this?
Upvotes: 0
Views: 257
Reputation: 14107
It's doable.
You can initialize a string as a normal array. It allows to do the computation over individual characters.
char x[] = "hello";
char y[] = { 'h', 'e', 'l', 'l', 'o', 0 };
Each digit can be computed as '0' + (value / (10**position)) % 10
.
Exemplary code that computes strings at compilation time for 2*x-1
and y*y
where x == 7
and y == 11
.
#include <stdio.h>
#define D(X) ('0' + (X) % 10)
#define S3(X) D((X)/100), D((X)/10), D(X)
#define S_O(X, Y) { 'S', S3(2*X-1), 'H', ';', 'S', S3(Y*Y), 'A', ';', 0 }
int main() {
char buf[] = S_O(7, 11);
puts(buf);
}
It prints:
S013H;S121A;
Still not perfect, because it adds those extra heading zeros but it may be good enough for OP's application.
Upvotes: 3
Reputation: 140960
I try to use macro expansion with a calculation resulting into a string
It is not possible to use just macro expansion to convert a result of calculation to a string. It is not (*feasibly) possible to use C preprocessor to convert the result of a calculation to a string.
How may I achieve my goal to avoid a function encapsulating this?
Strongly prefer in such cases to use a better and more powerful pre-processor than C preprocessor, like M4, Jinja2, PHP, or generate the source code.
*feasibly: To convert the result of a calculation to a string in C preprocessor, you would have to enumerate all possible cases one by one and prepare a string for it.
// calculate.h
#if N*2 == 2
#define RESULT_OF_N_MUL_2 "2"
#elif N*2 == 4
#define RESULT_OF_N_MUL_2 "4"
// etc. for __any__ number you want to handle
#endif
#if N*2-1 == 1
#define RESULT_OF_N_MUL_2_MINUS_1 "1"
#elif N*2-1 == 3
#define RESULT_OF_N_MUL_2_MINUS_1 "3"
// etc. for __any__ number you want to handle
#endif
#define S_O() \
"S" RESULT_OF_N_MUL_2_MINUS_1 "H;" \
"S" RESULT_OF_N_MUL_2 "H;"
#undef N
// main.c
#define N 10
#include "calculate.h"
int main() {
puts(S_O());
}
If you are open to such code, then you could use boost/preprocessor and apply stringify operation after the expansion, which works suprisingly good:
#include <boost/preprocessor.hpp>
#include <boost/preprocessor/arithmetic.hpp>
#include <boost/preprocessor/stringize.hpp>
#define S_O(N) \
"S" BOOST_PP_STRINGIZE(BOOST_PP_SUB(BOOST_PP_MUL(N, 2), 1)) "H;"
int main() {
puts(S_O(5)); // outputs "S9H;"
}
Behind the scenes, let's say BOOST_PP_*
enumerate all possible cases of addition one by one.
Upvotes: 2