C macro with flexible argument - c

I need to do something like :
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#define INCR(count,ARGS...) \
if(ARGS) \
count++; \
void main()
{
int count =1;
int flag =1;
INCR(count);
printf("count %d",count);
INCR(count,flag); /* flag determines if the count is to be incremented or not */
printf("count %d",count);
}
I get following errors:
sh-4.3$ gcc -o main*.c
main.c: In function 'main':
main.c:6:8: error: expected expression before ')' token
if(ARGS) \
^
main.c:15:5: note: in expansion of macro 'INCR'
INCR(count);
^
sh-4.3$
Here the counter is supposed to be incremented only if the flag is present. I need a macro with flexible number of arguments. Please help me on this

Based on the example in https://stackoverflow.com/a/11763277/5085250 you can do something like this:
#define GET_MACRO(_1,_2,NAME,...) NAME
#define INCR(...) GET_MACRO(__VA_ARGS__, INCR2, INCR1)(__VA_ARGS__)
#define INCR1(count)\
count++;
#define INCR2(count,flag)\
if(flag)count++;
Here I assume you want to increment if no flag is given. If you don't want to increment in that case you need to modify the INCR1 part...

Related

How can I make for loop of #define function?

I have #define function with argument such as DEF_GLOBAL_STRUCT(index) and I need to call this macro from 1 to 100. What is the best way? Can I use for loop?
I made the simple code to show my problem.
#include <stdio.h>
#include <stdint.h>
#define DEF_GLOBAL_STRUCT(index) uint8_t m_##index##_size=2; \
uint32_t m_##index##_data1=0; \
uint32_t m_##index##_data2=0;
DEF_GLOBAL_STRUCT(1)
DEF_GLOBAL_STRUCT(2)
DEF_GLOBAL_STRUCT(3)
// ...
DEF_GLOBAL_STRUCT(100)
int main()
{
printf("%u\n", m_1_size);
return 0;
}
Instead of 100 lines of define function call, can I use something like for loop. Or is there any other solution?
If I have all the control of the code I can define structure and declare it with array. But I can't do it. I need to use this type of define function. That is my limitation.
Your question is asking if you can mix C language with Preprocessor directives to automate the generation of code using both C language and Preprocessor directives.
The answer is not in the way you are trying to do it because of how the Preprocessor and the C compiler work.
The Preprocessor is a separate step from compilation. The idea is that the Preprocessor does a text replacement step of the C source code file to generate a new, temporary version of the C source code file which is then compiled by the C compiler.
It is two different steps and first the Preprocessor does its work and then the C compiler does its work.
What I would suggest is to write a simple program that generates an include file that contains the list of definitions you want to use. Then in the place where you want to put those definitions, use the #include directive to include it at that point.
So if you have a simple script or perhaps a C program something like:
#include <stdio.h>
int main ()
{
int i;
for (i = 1; i <= 100; i++) printf ("DEF_GLOBAL_STRUCT(%d)\n", i);
return 0;
}
Then you compile it and run it from a command line redirecting the output as in:
mygen >junk.h
then in the place you need these directives:
#include <stdio.h>
#include <stdint.h>
#define DEF_GLOBAL_STRUCT(index) uint8_t m_##index##_size=2; \
uint32_t m_##index##_data1=0; \
uint32_t m_##index##_data2=0;
#include "junk.h"
int main()
{
printf("%u\n", m_1_size);
return 0;
}
You can save some typing by defining another macro:
#include <stdio.h>
#include <stdint.h>
#define DEF_GLOBAL_STRUCT(index) uint8_t m_##index##_size=2; \
uint32_t m_##index##_data1=0; \
uint32_t m_##index##_data2=0;
#define DEF_GLOBAL_STRUCT_DECADE(tens) \
DEF_GLOBAL_STRUCT(tens##0) \
DEF_GLOBAL_STRUCT(tens##1) \
DEF_GLOBAL_STRUCT(tens##2) \
DEF_GLOBAL_STRUCT(tens##3) \
DEF_GLOBAL_STRUCT(tens##4) \
DEF_GLOBAL_STRUCT(tens##5) \
DEF_GLOBAL_STRUCT(tens##6) \
DEF_GLOBAL_STRUCT(tens##7) \
DEF_GLOBAL_STRUCT(tens##8) \
DEF_GLOBAL_STRUCT(tens##9)
DEF_GLOBAL_STRUCT(1)
DEF_GLOBAL_STRUCT(2)
DEF_GLOBAL_STRUCT(4)
DEF_GLOBAL_STRUCT(5)
DEF_GLOBAL_STRUCT(6)
DEF_GLOBAL_STRUCT(7)
DEF_GLOBAL_STRUCT(8)
DEF_GLOBAL_STRUCT(9)
DEF_GLOBAL_STRUCT_DECADE(1)
DEF_GLOBAL_STRUCT_DECADE(2)
DEF_GLOBAL_STRUCT_DECADE(3)
DEF_GLOBAL_STRUCT_DECADE(4)
DEF_GLOBAL_STRUCT_DECADE(5)
DEF_GLOBAL_STRUCT_DECADE(6)
DEF_GLOBAL_STRUCT_DECADE(7)
DEF_GLOBAL_STRUCT_DECADE(8)
DEF_GLOBAL_STRUCT_DECADE(9)
DEF_GLOBAL_STRUCT(100)
int main()
{
printf("%u\n", m_1_size);
return 0;
}

C preprocessing multi pass

I'm a littlebit confused about the behaviour of preprocessing in c.
#include <stdio.h>
#define myMacro anotherMacro
#define anotherMacro 6
int main()
{
int dummy = myMacro;
printf("dummy = %d", dummy);
return 0;
}
in the above code snippet, the result will 6. however the the macro expansion in the initial pass will replace "myMacro" by "anotherMacro".
this is means that preprocessor will make a second pass to resolve "anotherMacro" to value 6.
The preprocessor will make a second pass. He works through the source file line per line.
So if he reaches the first define
#define myMacro anotherMacro
he will replace all occurrences of myMacro with the string anotherMacro.
The file will look like this after the line is handled:
#include <stdio.h>
#define anotherMacro 6
int main()
{
int dummy = anotherMacro;
printf("dummy = %d", dummy);
return 0;
}
Now the preprocessor could continue with the next #define
and replace every anotherMacro with the text 6

How to get C to find the macro identifier given the numeric macro value?

Say I have some C code like:
#define FOO 2
#define BAR 3
#define BAZ 500
void get_value(int val) {
printf("The value is %s\n", some_function_or_macro_or_something(val));
}
int main(int argc, char** argv) {
get_value(BAZ);
get_value(FOO);
return 0;
}
and I want it to print out
"The value is BAZ"
and
"The value is FOO". But there are thousands of #defines, so I want to do it programmatically.
C is definitely capable of doing this using # stringizing operator, but you need to call macro with identifier directly:
#include <stdio.h>
#define FOO 2
#define BAR 3
#define BAZ 500
#define get_value(val) \
printf("The value is %s\n", #val);
int main(void)
{
get_value(BAZ);
get_value(FOO);
return 0;
}
In your example after passing value of e.g. BAZ to get_value function, the token BAZ is not recognized anymore, as arguments are passed by value. In other words macro identifier is gone (of course you can still stringize its replacement, see comment below).
What can I do more?
Here is some small hack to obey this "top-level" rule. Assuming that you have small amount of object-like macros (constants) with unique values, then you can do something like:
#include <stdio.h>
#define FOO 2
#define BAR 3
#define BAZ 500
#define STRINGIFY(val) #val
void get_value(int val) {
switch (val) {
case FOO :
printf("The value is %s\n", STRINGIFY(FOO)); break;
case BAR :
printf("The value is %s\n", STRINGIFY(BAR)); break;
case BAZ :
printf("The value is %s\n", STRINGIFY(BAZ)); break;
}
}
int main(int argc, char* argv) {
get_value(BAZ);
get_value(FOO);
return 0;
}
Result:
The value is BAZ
The value is FOO
Use the right tool for the job. Which tool knows all about macros? A compiler.
GNU gcc and clang both allow to dump the list of defined macros:
$ cc -E -dM -x c /usr/include/stdio.h
#define BUFSIZ 1024
#define EOF (-1)
#define FILENAME_MAX 1024
#define FOPEN_MAX 20
#define L_ctermid 1024
#define L_cuserid 17
#define L_tmpnam 1024
#define NULL ((void *)0)
#define P_tmpdir "/tmp/"
#define SEEK_CUR 1
#define SEEK_END 2
#define SEEK_SET 0
/* etc */
will list the whole shebang defined by <stdio.h> and everything it includes.
If you need to process this data programmatically in a C program,
#include <stdio.h>
#define BIG_ENOUGH 1024
int main (void)
{
char buffer[BIG_ENOUGH];
FILE *fp = popen ("cc -E -dM -x c /usr/include/stdio.h", "r");
while (fgets(buffer, sizeof buffer, fp) != NULL) {
char identifier[BIG_ENOUGH];
int value;
if (sscanf (buffer, "#define %s %d", identifier, &value) == 2) {
printf ("value %d is from macro %s\n", value, identifier);
}
}
fclose(fp);
return 0;
}
This prints here for stdio.h
value 1024 is from macro BUFSIZ
value 1024 is from macro FILENAME_MAX
value 20 is from macro FOPEN_MAX
value 1024 is from macro L_ctermid
value 17 is from macro L_cuserid
value 1024 is from macro L_tmpnam
value 1 is from macro SEEK_CUR
value 2 is from macro SEEK_END
value 0 is from macro SEEK_SET
value 308915776 is from macro TMP_MAX
[...]
Instead of stdio.h you simply use your file.c as input.
The classical, if somewhat heavyweight, approach is a table file:
enum.tab:
#ifndef DECL_CONST
# define DECL_CONST(name, value)
#endif
DECL_CONST(FOO, 2)
DECL_CONST(BAR, 3)
DECL_CONST(BAZ, 500)
#undef DECL_CONST
enum.h:
enum My_Enum
{
#define DECL_CONST(name, value) name = value,
#include "enum.tab"
};
char const* get_name(enum My_Enum value);
enum.c:
#include "enum.h"
char const* get_name(enum My_Enum value)
{
switch (value)
{
#define STR(name) #name
#define DECL_CONST(name, value) case value: return STR(name);
#include "enum.tab"
default:
return 0;
}
}
main.c:
#include "enum.h"
void process_value(int v)
{
char const* s = get_name((enum My_Enum) v);
if (s)
printf("The name of value %d is %s\n", v, s);
else
printf("There is no name for value %d\n", v);
}
int main()
{
process_value(1);
process_value(2);
process_value(3);
process_value(500);
process_value(501);
return 0;
}
Of course, you can expand this basic scheme to include as many attributes as you like and support any number of dependencies between them. Note that if you have more than one name defined to the same value, the compilation of switch statement will fail.
Not sure it is possible. GCC states in their manual :
There is no way to convert a macro argument into a character constant.

How to define macro function which support no input parameter and support also input parametr in the same time

I want to define a macro function which support at the same time:
1) No input parameter
2) Input parameters
some thing like that:
#define MACRO_TEST(X)\
printf("this is a test\n");\
printf("%d\n",x) // the last printf should not executed if there is no input parameter when calling the macro
In the main:
int main()
{
MACRO_TEST(); // This should display only the first printf in the macro
MACRO_TEST(5); // This should display both printf in the macro
}
You can use sizeof for this purpose.
Consider something like this:
#define MACRO_TEST(X) { \
int args[] = {X}; \
printf("this is a test\n");\
if(sizeof(args) > 0) \
printf("%d\n",*args); \
}
gcc and recent versions of MS compilers support variadic macros - that is macros that work similar to printf.
gcc documentation here:
http://gcc.gnu.org/onlinedocs/gcc/Variadic-Macros.html
Microsoft documentation here:
http://msdn.microsoft.com/en-us/library/ms177415(v=vs.80).aspx
Not exactly that but ...
#include <stdio.h>
#define MTEST_
#define MTEST__(x) printf("%d\n",x)
#define MACRO_TEST(x)\
printf("this is a test\n");\
MTEST_##x
int main(void)
{
MACRO_TEST();
MACRO_TEST(_(5));
return 0;
}
EDIT
And if 0 can be used as skip:
#include <stdio.h>
#define MACRO_TEST(x) \
do { \
printf("this is a test\n"); \
if (x +0) printf("%d\n", x +0); \
} while(0)
int main(void)
{
MACRO_TEST();
MACRO_TEST(5);
return 0;
}
The C99 standard says,
An identifier currently defined as an object-like macro shall not be redefined by another #define reprocessing directive unless the second definition is an object-like macro definition and the two replacement lists are identical. Likewise, an identifier currently defined as a function-like macro shall not be redefined by another #define preprocessing directive unless the second definition is a function-like macro definition that has the same number and spelling of parameters, and the two replacement lists are identical.
I think compiler prompts a warning of redefined MACRO. Hence it is not possible.

printf(" LIST.H ") where LIST.H is a macro

#include <stdio.h>
#include<stdlib.h>
#define LIST.H onus;
int main ()
{
char *p,*s;
printf(" LIST.H ");
}
I expect LIST.H to print onus as out put.
But this does not happen.
upon compiling I get a warning
temp.c:3:13: warning: missing whitespace after the macro name
and the output is LIST.H not onus.
How can I get desired thing printed by the above macro?
UPDATE
I want to have the output
as onus with one space before and after the string.
Macros names cannot have . inside them. That's why you get the warning:
warning: missing whitespace after the macro name, after LIST it expects a space, but it gets a . instead.
Also, when a macro name is inside a string(between "string") it is not replaced by the macro definition.
You could do this instead:
#define LISTH "onus"
// and then
printf(LISTH);
which the preprocessor will transform to:
printf("onus");
If you do:
#define LISTH "onus";
the preprocessor will transform it to:
printf("onus";);
which won't compile.
Firstly, you can't use . in macro names.
Secondly, you should "expect" it to print ouns;, since you included a ; into your macro definition.
Thirdly, in order to achieve that you can use "stringization" macro-operator # with some helper macros
#define TO_STRING_(x) #x
#define TO_STRING(x) TO_STRING_(x)
#define LIST_H onus
...
printf(" " TO_STRING(LIST_H) " ");
or, better
printf(" %s ", TO_STRING(LIST_H));
#include <stdio.h>
#define LIST_H "onus"
int main()
{
printf(LIST_H);
}
macros in strings aren't resolved, you need to layers of macro resolution to do that:
#define __STR(x) #x
#define _STR(x) __STR(x)
printf(_STR(LIST));
you also cannot have dots in macro defines last I checked, which would be what your error is about, so rather use LIST_H...

Resources