I'm trying to create a macro in C in order to create the correct pragma declaration.
_pragma(section .BLOCK1) //Correct but deprecated
_pragma(section ".BLOCK1") //Correct without warning
Following code is working, but the compiler gives me a warning (deprecated declaration):
#define DO_PRAGMA(x) _Pragma(#x)
#define PRAGMA(number) \
DO_PRAGMA(section .BLOCK##number)
PRAGMA(1)
How I can include the double quotes in the macro?
I have already tried inserting "\"", but it is not working because the string is interpreted directly.
You can pass this to a helper macro which expands and stringifies the arguments.
#define _stringify(_x) #_x
#define DO_PRAGMA(a) _Pragma(_stringify(a))
#define PRAGMA(number) \
DO_PRAGMA(section _stringify(.BLOCK##number))
The correct way to add double quotes to a macro is indeed to use backslash i.e.:
#define STRING "\"string\""
"string" is now stored in STRING.
To concatenate a number into your macro string you can do something like, but it needs to be stored in non const char array:
#define STRING "section \".BLOCK%d\""
#define CONV(str, n) sprintf(str, STRING, n)
//...
char str [50];
CONV(str, 1);
DO_PRAGMA(str);
//...
If you haven't already, check pragma documentation and this usage example.
Related
I'm writing a complex macro and I need to pass also array initializer. Basically I have trouble to do:
#define INIT_ARR(VAR_NAME,ARR_DATA) int VAR_NAME[] = ARR_DATA
then I would call it
INIT_ARR(myNm,{1,2,3});
but preprocessors interprets any commas (also the one inside curly braces) as new macro parameter so it gives me error:
error: #55-D: too many arguments in invocation of macro "INIT_ARR"
preprocessor does not ignore () so I can do:
#define INIT_ARR(VAR_NAME,ARR_DATA) int VAR_NAME[] = {ARR_DATA}
INIT_ARR(myNm,(1,2,3));
but then it is interpreted as
int myNm[] = {(1,2,3)};
which is not correct for C.
Is there a way how to do it?? For example remove braces from parameter?
I think I cracked it:
#define myArgs(...) __VA_ARGS__
#define INIT_ARR(VAR_NAME,ARR_DATA) int VAR_NAME[] = {myArgs ARR_DATA}
INIT_ARR(myArr,(1,2,3,4));
will be interpreted correctly as:
int myArr[] = {1,2,3,4};
annoying_squid's answer helped me to figure it out...
You can use variable number of arguments with the macro as -
#define INIT_ARR(VAR_NAME, ...) int VAR_NAME[] = {__VA_ARGS__}
I always write below code for debug purpose:
printf("%s:%d this is a string %s int %d",__FUNCTION__,__LINE__,strval,intval);
Now since the first part (FUNCTION,LINE) is always used, so I wish to create a macro to do it and just append other debug strings.
Maybe looks like:
#define MYPRINT(args...) printf("%s:%d",__FUNCTION__,__LINE__);printf(##args)
But I wish to use one statement rather than two as above! Is it possible?
Clarify not duplicate of this one
This is different because I wish to add some new field into print command. actually answers here is great, thanks for all's help!
If you want a single call to printf(), your MYPRINT needs to be aware of a format string. You can try something like this, so long as the format string is a literal:
#define MYPRINT(FMT, ...) printf("%s:%d " FMT, __FUNCTION__, __LINE__, ##__VA_ARGS__)
The ## is a GCC (and perhaps others) compiler extension that swallows the comma in the case __VA_ARGS__ is actually empty. If your compiler does not support it, leave it off.
You can use a variadic macro and use , to have one statement:
#define MYPRINT(...) (printf("%s:%d",__FUNCTION__,__LINE__), printf(__VA_ARGS__))
How about this :
#include <stdio.h>
#define MYPRINT(fmt, ...) \
printf("[%s]:%d - " fmt "\n", __FUNCTION__, __LINE__, __VA_ARGS__)
int main() {
char const *s = "My string";
int i = 42;
MYPRINT("%s, %d", s, i);
}
Outputs :
[main]:8 - My string, 42
Is it possible to expand a macro which accepts multiple arguments to a different macro if first argument is not the expected value
E.g
int main()
{
PRINT(2, "%d%d\n", i, j); //should expand to syslog(2, "%d%d\n", i, j)
PRINT("%d%d\n", i, j); //arg1 which is expected to be an int is not preset.
/* This should expand differently may be to a default level say 3. syslog(3, "%d%d\n", i,j); */
}
I would have tried this kind of over loading if I knew total number of args.
I really recommend to write two separate macros for this, just as you would write two differently named functions for the two signatues in C. (I would rather write macros that tell you what level they are explicitly, like ERROR(...), WARNING(..) etc. than introduce a default argument.)
That said, there are two possibilities to achieve what you want.
C11 _Generic selections
The _Generic keyword was introduced with C11. It allows to expand macros in a switch-like manner according to the type of an argument; Robert Gamble has a good introduction.
You want to distinguish two cases: First argument is a string and first argument is an integer. A drawback is that in _Generic, a string literal isn't treated as char * or const char *, but as char[size]. For example, "%d" is a char[3].
In your case, we can get around this by treating a string as anything that isn't an integer. The compiler will sort out all non-string, non-integer arguments later. So:
#define PRINT(fmt, ...) \
_Generic(fmt, \
int: syslog(fmt, __VA_ARGS__), \
default: syslog(3, fmt, __VA_ARGS__))
There are drawbacks: You can't have a single-argument call, because that would leave a comma in the call. (gcc's ##__VA_ARGS__ gets around that.) And the _Generic keyword is not yet widely implemented; this solution will make your code highly unportable.
String introspection hack
Ordinary C99 macros have no information on their type. C code can make a guess, however. Here's an example that checks whether a macro argument is a string literal:
#define PRINT(sev, ...) \
if (#sev[0] == '"') syslog(3, sev, __VA_ARGS); \
else syslog(sev, __VA_ARGS__);
This works -- almost. The compiler will probably compile the constant condition away and only gererate code for one of the branches. But it will parse the branches anyway and the dead branch will have a wrong function signature, which will generate warnings.
You can get around this by writing a variadic front-end function in C. Here's an example that works:
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#define HEAD(X, ...) X
#define STR_(x) #x
#define STR(x) STR_(x)
#define PRINT(...) \
msg(*STR(HEAD(__VA_ARGS__)) == '"', __VA_ARGS__)
int msg(int dflt, ...)
{
va_list va;
int sev = 3;
const char *fmt;
va_start(va, dflt);
if (!dflt) sev = va_arg(va, int);
fmt = va_arg(va, const char *);
fprintf(stderr, "[%d] ", sev);
vfprintf(stderr, fmt, va);
fprintf(stderr, "\n");
va_end(va);
return 0;
}
int main()
{
PRINT(1, "Incompatible types %s and %s", "Apple", "Orange");
PRINT("Microphone test: %d, %d, %d, ...", 1, 2, 3);
return 0;
}
This solution is dangerous, because the msg function is only safe if it is generated by the macro. And the macro is only safe if the format string is a string literal beginning with a double quote. The macro expands the arguments by one boolean argument to the left and hides the argument incompatibility in a variadic argument list.
It may be a nice trick, but you'll be better off having separate, clearly named macros.
C macros do not have the ability to inspect their arguments. As noted in the answer you posted, there is a sneaky way to do different things based on the number of arguments, but that's the extent of it. If you already have a variable number of arguments outside of the overload you are trying to do, it will not be possible. If all you need is a default level:
#define PRINTNORM(...) PRINT(3, __VA_ARGS__)
or whatever you'd like to call it. IMHO, cleaner code than overloading PRINT.
Simply use another value for your need. And perhaps a bit of magic with variadic macro would help.
something like:
#define PRINT( print_level , print_string , ... )\
switch( print_level ) \
/* as many syslog cas as needed */
case( 5 ):\
case( 4 ):\
case( 3 ):\
case( 2 ):\
case( 2 ):\
case( 1 ):\
syslog( print_level , __VA_ARGS__ );\
break ; \
default: \
case( 0 ): \
printf( __VA_ARGS__ ); \ /* else we simply want to print it */
break ;
Edit:
Doc on variadic macro: https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html
P99 has conditional macro evaluation. Here you could probably use something like P99_IF_EMPTY for something like
#define PRINT(LEV, ...) my_print(P99_IF_EMPTY(LEV)(3)(LEV), __VA_ARGS__)
this would still have you insert a , for the case of the empty argument but comes probably close to what you want to achieve.
Optional arguments coming before other mandatory arguments can potentially be handled by folding them together in parentheses:
PRINT((2, "%d%d\n"), i, j);
PRINT("%d%d\n", i, j);
Define PRINT like this:
#define PRINT(SL, ...) PRINT_LEVEL(APPLY(CAT(LEVEL, IS_SPLIT(SL)), IDENTITY SL), APPLY(CAT(FSTRING, IS_SPLIT(SL)), IDENTITY SL), __VA_ARGS__)
#define PRINT_LEVEL(LEVEL, ...) syslog(LEVEL, __VA_ARGS__)
PRINT detects whether the first argument is an atom (just the format string) or a parenthesized list of two elements (printlevel + string), and expands into the real implementation PRINT_LEVEL accordingly, either extracting the level from the first argument, or supplying a default value.
Definitions for IS_SPLIT and the other helpers are as follows:
#define LEVEL_0(_S) 3
#define LEVEL_1(L, S) L
#define FSTRING_0(S) K_##S
#define FSTRING_1(L, S) S
#define CAT(A, B) CAT_(A, B)
#define CAT_(A, B) A ## B
#define APPLY(F, ...) F(__VA_ARGS__)
#define IDENTITY(...) __VA_ARGS__
#define K_IDENTITY
#define IS_SPLIT(...) IS_SPLIT_1(IDENTITY __VA_ARGS__)
#define IS_SPLIT_1(...) IS_SPLIT_2(__VA_ARGS__, _1, _0, _)
#define IS_SPLIT_2(_X, _Y, R, ...) R
Is is possible to convert any variable of any type to string?
I wrote the following
#define TO_STRING(val) #val
Is this a valid way of converting a variable into a string?
I think the code below will do your work. I uses the standard sprintf function, which prints data from any type to a string, instead to stdout. Code:
#include <stdio.h>
#define INT_FORMAT "%d"
#define FLOAT_FORMAT "%f"
#define DOUBLE_FORMAT "%lf"
#define LL_FORMAT "%lld"
// ect ...
#define CONVERT_TO_STRING(FORMAT, VARIABLE, LOCATION) \
do { \
sprintf(LOCATION, FORMAT, VARIABLE); \
} while(false)
int main() {
char from_int[30];
char from_float[30];
char from_double[30];
char from_ll[30];
CONVERT_TO_STRING(INT_FORMAT, 34, from_int);
CONVERT_TO_STRING(FLOAT_FORMAT, 34.234, from_float);
CONVERT_TO_STRING(DOUBLE_FORMAT, 3.14159265, from_double);
CONVERT_TO_STRING(LL_FORMAT, 9093042143018LL, from_ll);
puts(from_int);
puts(from_float);
puts(from_double);
puts(from_ll);
return 0;
}
You will get a string version of the variable's name, i.e. it will convert a to "a". The #when used like this is called the stringification operator.
For example:
#define TO_STRING(val) #val
int main(void)
{
const int a = 12;
print("a is %s\n", TO_STRING(a));
return 0;
}
This will print a is a.
What do you expect to happen?
You can't get the variable's value, of course, since that's not available when the pre-processor runs (which is at compile-time).
try this will work with integers: edit the format string for other data types.
sprintf(str,"%d",value);
What does ## do in C?
Example:
typedef struct
{
unsigned int bit0:1;
unsigned int bit1:1;
unsigned int bit2:1;
unsigned int bit3:1;
unsigned int bit4:1;
unsigned int bit5:1;
unsigned int bit6:1;
unsigned int bit7:1;
} _io_reg;
#define REGISTER_BIT(rg,bt) ((volatile _io_reg*)&rg)->bit##bt
(I know what it all does besides the ## part.)
It is string concatenation, as part of the preprocessor macro.
(In this context, "string" refers to a preprocessor token of course, or a "string of source code", and not a C-string.)
It's called the pasting operator; it concatenates the text in bt with the text bit. So for example, if your macro invocation was
REGISTER_BIT(x, 4)
It would expand to
((volatile _io_reg*)&x)->bit4
Without it, you couldn't put a macro argument directly beside text in the macro body, because then the text would touch the argument name and become part of the same token, and it'd become a different name.
The operator ## concatenates two arguments leaving no blank spaces between them:
#define glue(a,b) a ## b
glue(c,out) << "test";
That is the token pasting operator.
That's part of the macro definition.
It allows you to concatenate strings inside the macro.
In your case, you can use bt from 7 to 0 like this:
REGISTER_BIT(myreg, 0)
and it will be expanded as:
((volatile _io_reg*)&myreg)->bit0
Without this, you'd have to define the bit part of the macro as one of the macro's arguments:
#define REGISTER_BIT(rg,bt) ((volatile _io_reg*)&rg)->bt
where the usage would be:
REGISTER_BIT(myreg, bit0)
which is more cumbersome.
This also allows you to build new names.
Assume you have these macros:
#define AAA_POS 1
#define AAA_MASK (1 << AAA_POS)
#define BBB_POS 2
#define BBB_MASK (1 << BBB_POS)
and you want a macro that extracts AAA from a bit vector. You can write it like this:
#define EXTRACT(bv, field) ((bv & field##_MASK) >> field##_POS)
and then you use it like this:
EXTRACT(my_bitvector, AAA)
It's not a C construct, it's a preprocessor feature. In this case it's meant to evaluate the bt variable and concatenate it with the bit prefix. Without the hashes you would have bitbt there, which obviously would not work.
Here's an example from ffmpeg, a macro that registers both audio and video filters:
#define REGISTER_FILTER(X, x, y) \
{ \
extern AVFilter ff_##y##_##x; \
if (CONFIG_##X##_FILTER) \
avfilter_register(&ff_##y##_##x); \
}
and usage can be:
REGISTER_FILTER(AECHO,aecho,af);
REGISTER_FILTER(VFLIP,vflip,vf);