C macro defines variable length value - c

I has implemented own tmpnam() function for creating temporary files. I use following defines for adjust this one:
/* The length of random string. In /tmp/test143276 is 143246 */
#define RND_ROUND 6
/* Used as a minimal bound produced by number generator */
#define RND_MIN 100000
/* Used as a maximum bound produced by number generator */
#define RND_MAX 1000000
As you can see the real needed macro is RND_ROUND and others are derivative to pass to the number generator. And the formula for generating is:
RND_MIN = 1 and [RND_ROUND-1] zeros
RND_MAX = 1 and [RND_ROUND] zeros
Question: How can I create some macro which will produce RND_MIN and RND_MAX based on RND_ROUND at compile time?
Example:
#define RND_ROUND 6
// somehow define those RND_MIN and RND_MAX
...
int32_t random = g_rand_int_range(generator, RND_MIN(RND_ROUND), RND_MAX(RND_ROUND));

You can use the power function to do the work.
#define RND_MIN (pow (10, RND_ROUND-1))
#define RND_MAX (pow (10, RND_ROUND))
Or depending on the passed argument.
#define RND_MIN(val) (pow (10, (val)-1))
#define RND_MAX(val) (pow (10, (val)))

If I am correct you can use power function:
#define RND_MIN(RND_ROUND) pow(10, RND_ROUND - 1)
#define RND_MAX(RND_ROUND) pow(10, RND_ROUND)
You may like to read: How to simplify this power equation?

I would suggest you to forget about RND_ROUND: this is compile time, anyway!
#define RND_BASE 1000000
#define RND_MIN RND_BASE
#define RND_MAX (RND_BASE*10)
Now, if you really need RND_ROUND, RND_MIN and RND_MAX at compile time and not being expanded to pow, assuming your RND_ROUND is not you may branch it with #if (note that g_rand_int_range is limited to gint32, so RND_MAX<2^31=2'147'483'648<10^10 is possible):
#if RND_ROUND <= 1
# define RND_MIN 1
#elif RND_ROUND <= 2
# define RND_MIN 10
#elif RND_ROUND <= 3
# define RND_MIN 100
#elif RND_ROUND <= 4
# define RND_MIN 1000
#elif RND_ROUND <= 5
# define RND_MIN 10000
#elif RND_ROUND <= 6
# define RND_MIN 100000
#elif RND_ROUND <= 7
# define RND_MIN 1000000
#elif RND_ROUND <= 8
# define RND_MIN 10000000
#else
# define RND_MIN 100000000
#endif
#define RND_MAX (RND_MIN*10)
This will also be safer, limiting RND_ROUND so that there will not be integer overflows.

Related

Can C-preprocessor can output as a string the evaluation of compiled known constants values(e.g. 150000UL/1000UL)? #define arithmetics

I'm wondering if it can be written that the prepocessor evaluates assigned constants known at compile time and returns the result as a string. I believe the answer is no or complex, but I'll give a try.
Basically I have constants which are expressed in milliseconds but I want to display the results as secs, therefore divide by 1000, and wonder because all is known at compile time, if the preprocessor can directly put the result of this division into the code rather than eval at runtime.
Example:
#define FREQ_AUTO_WHEN_RELAY_ON 150000UL
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
STR( FREQ_AUTO_WHEN_RELAY_ON/1000UL ) " secs"
would yield to "150000UL/1000UL secs"
which is not I want to display, aka "150 secs"
Thanks
You have to first prepare a header with all possible outputs:
// calculate.h
#if VALUE == 1
#define RESULT 1
#elif VALUE == 2
#define RESULT 2
/* etc. millions of lines */
#elif VALUE == 150
#define RESULT 150
#endif
Then you can do:
#define VALUE FREQ_AUTO_WHEN_RELAY_ON/1000UL
#include "calculate.h"
STR(VALUE)
Similarly, you first have to define a matrix of all possible combinations of values:
#define DIV_1UL_1UL 1
#define DIV_1UL_2UL 0
#define DIV_2UL_1UL 2
/* etc. really millions of lines */
#define DIV_150000UL_1000UL 150
Then you can:
#define DIV(a, b) DIV_##a##_##b
#define XDIV(a, b) DIV(a, b)
STR(XDIV(FREQ_AUTO_WHEN_RELAY_ON, 1000UL))
Can C-preprocessor can output as a string the evaluation of compiled known constants values(e.g. 150000UL/1000UL)?
Yes, but it's not practical. Instead, generate the header file from a build system.

Expansion of C preprocessor macros with integer arithmetic in a text file?

On my system, I have a /usr/include directory, with a curl/options.h file in it, which contains a preprocessor definition of CURLOT_FLAG_ALIAS.
If I have the following test.txt:
#include "curl/options.h"
curlot flag alias is: CURLOT_FLAG_ALIAS
Then I can do this to expand the macro in the text file:
$ gcc -E -P -x c -I/usr/include test.txt
typedef enum {
CURLOT_LONG,
CURLOT_VALUES,
CURLOT_OFF_T,
CURLOT_OBJECT,
CURLOT_STRING,
CURLOT_SLIST,
CURLOT_CBPTR,
CURLOT_BLOB,
CURLOT_FUNCTION
} curl_easytype;
struct curl_easyoption {
const char *name;
CURLoption id;
curl_easytype type;
unsigned int flags;
};
CURL_EXTERN const struct curl_easyoption *
curl_easy_option_by_name(const char *name);
CURL_EXTERN const struct curl_easyoption *
curl_easy_option_by_id(CURLoption id);
CURL_EXTERN const struct curl_easyoption *
curl_easy_option_next(const struct curl_easyoption *prev);
curlot flag alias is: (1<<0)
However, this approach also dumped all the function definitions in curl/options.h; ultimately, to just process the text file, this gives a much "cleaner" result - have test.txt be just:
curlot flag alias is: CURLOT_FLAG_ALIAS
... and then use -imacros switch (and pipe into grep to remove empty lines):
$ gcc -E -P -x c -I/usr/include -imacros curl/options.h test.txt | grep -v '^[[:space:]]*$'
curlot flag alias is: (1<<0)
Great - except, I do not really want the (1<<0) in the text output - I want its expanded integer decimal value, 1; in other words, I'd want the text output to be:
curlot flag alias is: 1
I guess one way would be, to keep the original and modified text file, identify range of characters in the modified file of the parts that are changed from the original file, here (1<<0) - then feed that string into some calculator, then replace it with the output of the calculator. However, while (1<<0) is parseable by calculators like wcalc - I doubt many common idioms like (1u<<32) would be parseable by it, so even strings like these would have to go through the compiler I guess, and the C compiler is not REPL, so it cannot "just" give a value for an input like (1<<0) ...
Now, I'm aware the C preprocessor does not do arithmetic, apart from conditionals ( Can the C preprocessor perform integer arithmetic? ), so maybe what I want to achieve is impossible with C preprocessor (and possibly compiler) - if that is the case, are there any other tools to help me achieve replacement and expansion of C macros with integer arithmetic in a text file?
One common approach is to actually compile and execute the code instead of merely preprocessing it. Have a file make_test.c containing:
#include <stdio.h>
#include "curl/options.h"
int main(void) {
printf("curlot flag alias is: %d\n", CURLOT_FLAG_ALIAS);
return 0;
}
and then have your build process compile and execute this program.
gcc -o make_test -I /usr/include make_test.c
./make_test
Yes, you can extract the result of evaluating an integer constant expression using a system commonly referred to as preprocessor slots:
slot.h:
// slot.h
#define DIG DIG_CATe(DIG_2,DIG_1)
#define DIG_CATe(a,b) DIG_CAT(a,b)
#define DIG_CAT(a,b) a##b
#undef DIG_1
#if (SLOT) % 10 == 0
#define DIG_1 0
#elif (SLOT) % 10 == 1
#define DIG_1 1
#elif (SLOT) % 10 == 2
#define DIG_1 2
#elif (SLOT) % 10 == 3
#define DIG_1 3
#elif (SLOT) % 10 == 4
#define DIG_1 4
#elif (SLOT) % 10 == 5
#define DIG_1 5
#elif (SLOT) % 10 == 6
#define DIG_1 6
#elif (SLOT) % 10 == 7
#define DIG_1 7
#elif (SLOT) % 10 == 8
#define DIG_1 8
#elif (SLOT) % 10 == 9
#define DIG_1 9
#endif
#undef DIG_2
#if (SLOT/10) % 10 == 0
#define DIG_2 0
#elif (SLOT/10) % 10 == 1
#define DIG_2 1
#elif (SLOT/10) % 10 == 2
#define DIG_2 2
#elif (SLOT/10) % 10 == 3
#define DIG_2 3
#elif (SLOT/10) % 10 == 4
#define DIG_2 4
#elif (SLOT/10) % 10 == 5
#define DIG_2 5
#elif (SLOT/10) % 10 == 6
#define DIG_2 6
#elif (SLOT/10) % 10 == 7
#define DIG_2 7
#elif (SLOT/10) % 10 == 8
#define DIG_2 8
#elif (SLOT/10) % 10 == 9
#define DIG_2 9
#endif
// ...
#undef SLOT
test.c:
#define SLOT 2*5
#include "slot.h"
result 1: DIG
#define SLOT (1+3*4)*2
#include "slot.h"
result 2: DIG
output (cc -P -E):
result 1: 10
result 2: 26
Although the utility of using this for your problem is questionable.

How do i make preprocessor macros evaluate code before compilation

i'm using macros to define static size for some arrays in my code, i have defined a config macro variable at the top of my code and some macro variables depend on said macro variable. i can make a function that takes that value and returns the required size of the array but that would execute in runtime and i'll need to use VLAs.
example below shows macro for SIZE of a number (with no repeating digits) and whether that number can begin with a zero ("0123" vs "1234").
code to calculate LIMIT in runtime:
int limit(int size, int npz){
l = npz ? 9 : 10;
for(int i = 1; i < size; i++)
l *= 10 - i;
return l;
}
i manually calculated the amount of said numbers for all values. is there a work around?
#define SIZE 4 // 1 .. 10
#define NO_PADDING_ZERO 1 // 1 | 0
#if NO_PADDING_ZERO
#if SIZE == 1
#define LIMIT 9
#elif SIZE == 2
#define LIMIT 81
#elif SIZE == 3
#define LIMIT 648
#elif SIZE == 4
#define LIMIT 4536
#elif SIZE == 5
#define LIMIT 27216
#elif SIZE == 6
#define LIMIT 136080
#elif SIZE == 7
#define LIMIT 544320
#elif SIZE == 8
#define LIMIT 1632960
#else
#define LIMIT 3265920
#endif
#else
#if SIZE == 1
#define LIMIT 10
#elif SIZE == 2
#define LIMIT 90
#elif SIZE == 3
#define LIMIT 720
#elif SIZE == 4
#define LIMIT 5040
#elif SIZE == 5
#define LIMIT 30240
#elif SIZE == 6
#define LIMIT 151200
#elif SIZE == 7
#define LIMIT 604800
#elif SIZE == 8
#define LIMIT 1814400
#else
#define LIMIT 3628800
#endif
#endif
The workaround could be to generate C code from something else.
Consider learning more, using GPP or your own C code generator (perhaps using GNU bison and in some simple cases GNU gawk or GNU autoconf).
Observe that on Linux or POSIX, you could generate C code, compile it as a plugin, and dlopen(3) that plugin. For a useless example, see manydl.c. For useful (but obsolete) example, see my old GCC MELT.
Another approach (GCC specific) might be to extend your compiler with GCC plugins. See bismon.
You can also generate machine code (in your program) using GNU lightning or (in C++) asmjit. Then read the Dragon book and this answer.
Read some books by Jacques Pitrat explaining that metaprogramming approach (reused in RefPerSys)
The concepts related to partial evaluation are relevant.
It's this some kind of the factorial?
(10 - NO_PADDING_ZERO) * 9 * 8 * ... * (10 - LIMIT)
You can use this in the loop expression in a macro or an inline function and the optimizing compiler will compute it at compile time.
#include <bool.h>
inline int limit(int size, bool npz){
int l = 10 - npz;
for(int i = 1; i < size; i++)
l *= 10 - i;
return l;
}
#define LIMIT (limit(SIZE, NO_PADDING_ZERO))
If you wish you may define a precomputed array and use
#define LIMIT (array[SIZE][NO_PADDING_ZERO])

How to define a constant conditionally

I want to define some constants in my C file.
Its assembly code like this:
Const1 = 0
Const2 = 0
IF Condition1_SUPPORT
Const1 = Const1 or (1 shl 6)
Const2 = Const2 or (1 shl 3)
ENDIF
IF Condition2_SUPPORT
Const1 = Const1 or (1 shl 5)
Const2 = Const2 or (1 shl 2)
ENDIF
Could you tell me the simplest way to implement this?
And it should be flexible enough because the number of both my constants and conditions is over 10.
After seeing the first three answers, I guess I need to explain more;
What I want to know is how to redefine my constant based on its previous value.
You can do so using preprocessing directives:
#if Condition1_SUPPORT
#define Const1 (1 << 6)
// ...
#elif Condition2_SUPPORT
#define Const1 (1 << 5)
// ...
#endif
To address the edit to the question: you can't redefine a macro based on its previous value. A macro can only have one value at a time and its replacement list is only evaluated when it is invoked, not when it is defined. For example, this is not possible:
#define A 10
#define A A + 10
First, it is an illicit redefinition of the macro: when the second line is handled, A is already defined as a macro, and so it cannot be redefined with a different replacement (you have to #undef the macro name first).
Second, were this licit (and many compilers do accept it), the second line, when invoked, would evaluate to A + 10, not 10 + 10 or 20 as you want: by the time the second macro definition could be invoked, the first definition no longer exists.
You can, however, use different names, like so:
#define INITIAL_A 10
#define A INITIAL_A + 10
You should consider getting one of the introductory books from The Definitive C Book Guide and List; any of them would cover what can be accomplished using the preprocessing directives in some detail.
You can't redefine the value of a constant once you assign it -- if you could, it wouldn't be a constant, would it? Since it looks like you're trying to set various bits in a constant based on preprocessor flags, you could #define separate constants for each condition's contribution, then build the final value at the end:
#if Condition1_SUPPORT
# define Const1_Cond1_Bit (1 << 6)
# define Const2_Cond1_Bit (1 << 3)
#else
# define Const1_Cond1_Bit (0)
# define Const2_Cond1_Bit (0)
#endif
#if Condition2_SUPPORT
# define Const1_Cond2_Bit (1 << 5)
# define Const2_Cond2_Bit (1 << 2)
#else
# define Const1_Cond2_Bit (0)
# define Const2_Cond2_Bit (0)
#endif
#define Const1 (Const1_Cond1_Bit | Const1_Cond2_Bit)
#define Const2 (Const2_Cond1_Bit | Const2_Cond2_Bit)
You can then #undef all the intermediate constants, if namespace pollution is a concern.
You can use pre processor macros to conditionally define a constant variable, like
#if SOME_CONDITION
const int my_constant = 10;
#else
const int my_constant = 5;
#endif
In C, you would use preprocessor macros to accomplish that:
#ifdef COND1_SUPPORT
#define CONST1 CONST1_VAL1
#define CONST2 CONST2_VAL1
#elif COND2_SUPPORT
#define CONST1 CONST1_VAL2
#define CONST2 CONST2_VAL2
#endif

Cleanest way to store lists of filter coefficients in a C header

I have many (~100 or so) filter coefficients calculated with the aid of some Matlab and Excel that I want to dump into a C header file for general use, but I'm not sure what the best way to do this would be. I was starting out as so:
#define BUTTER 1
#define BESSEL 2
#define CHEBY 3
#if FILT_TYPE == BUTTER
#if FILT_ROLLOFF == 0.010
#define B0 256
#define B1 512
#define B2 256
#define A1 467
#define A2 -214
#elif FILT_ROLLOFF == 0.015
#define B0 256
#define B1 512
// and so on...
However, if I do that and shove them all into a header, I need to set the conditionals (FILT_TYPE, FILT_ROLLOFF) in my source before including it, which seems kinda nasty. What's more, if I have 2+ different filters that want different roll-offs/filter types it won't work. I could #undef my 5 coefficients (A1-2, B0-2) in that coefficients file, but it still seems wrong to have to insert an #include buried in code.
Edit:
This is for an embedded 8-bit processor with very small (2-4K) code space. I cannot seem to accomplish this by storing them into an array of structs because the space it consumes is unacceptable. Even declaring them all constant, my compiler will not 'optimize them away' so I'm left with a shade over 1.2K of extra binary data.
The below does not work.
typedef struct {
int16_t b0, b1, b2, a1, a2;
} filtCoeff;
const filtCoeff butter[41] = {
{256,512,256,467,-214},
{256,512,256,444,-196},
{255,512,255,422,-179},
// ...
};
const filtCoeff bessel[41] // ...
Put the filter coefficients in an array of structs. Instead of worrying about header files, I would just put the declaration of the array pointer in the .h files and define them in a specific .c file that you link in.
You could use token concatenation to get these to be parameters to a macro.
#define BUTTER 1
#define BESSEL 2
#define CHEBY 3
#define ROLLOFF_0_010 1
#define ROLLOFF_0_015 2
// BUTTER, ROLLOFF_0_010
#define B0_11 256
#define B1_11 512
#define B2_11 256
#define A1_11 467
#define A2_11 -214
// BUTTER, ROLLOFF_0_015
#define B0_12 256
#define B1_12 512
// ...
#define B0_(type, rolloff) (BO_##type##rolloff)
#define B1_(type, rolloff) (B1_##type##rolloff)
#define B2_(type, rolloff) (B2_##type##rolloff)
#define A1_(type, rolloff) (A1_##type##rolloff)
#define A2_(type, rolloff) (A2_##type##rolloff)
/*
* This two level define is so that the parameters to these macros
* get run through the macro process. That is, B1_(BUTTER, ROLLOFF_0_010)
* evaluates as B1_BUTTERROLLOFF_0_010, while B1(BUTTER, ROLLOFF_0_010)
* evaluates as B1_11 and thus as 256.
*/
#define B0(type, rolloff) B0_(type, rolloff)
#define B1(type, rolloff) B1_(type, rolloff)
#define B2(type, rolloff) B2_(type, rolloff)
#define A1(type, rolloff) A1_(type, rolloff)
#define A2(type, rolloff) A2_(type, rolloff)
B1(BUTTER, ROLLOFF_0_015) is now equivalent to 512. Then you can build any more complicated things as macros. E.g.:
#define CROSSPRODUCT(type, rolloff, values) \
B0(type, rolloff) * ((values)[0]) + \
B1(type, rolloff) * ((values)[1]) + \
...
You could also put your code in another file and use TYPE and ROLLOFF. Then just #define TYPE and ROLLOFF and include the other file. I think I prefer using a macro though.

Resources