why the macro definition "#define yyparse ol_parser_parse" can work? - c

Before, I did't read the generated code from yacc carefully. Now I saw one snippet of code like this:
#define yyparse ol_parser_parse
I know yyparse's definition as follows:
int yyparse (void)
so, this macro definition should be interpreted as: every "ol_parser_parse" in code will be replaced by "yyparse". And I wrote some code for testing that:
#include <stdio.h>
#define yyparse ol_parser_parse
void yyparse()
{
printf("hello world\n");
}
void main()
{
ol_parser_parse();
}
It worked!
But according to the definition about "macro definition":
#define <identifier>(<parameter list>) <replacement token list>
I am confused by this. Who can help me explain this? Thanks in advance!

Here's your code as seen by the compiler after the substitution is performed:
#include <stdio.h>
void ol_parser_parse()
{
printf("hello world\n");
}
void main()
{
ol_parser_parse();
}
There's nothing mysterious about it at that point. Every instance of "yyparse" becomes "ol_parser_parse" on every line following the #define.
In the documentation identifier means the thing being substituted and replacement token list is what you're substituting it with. You can also have parameters, like:
#define TIMES_TWO(n) ((n) * 2)
Where you can then do:
int x = TIMES_TWO(3);
Where that's equivalent to:
int x = ((3) * 2);
Where the extra brackets are so you can do this and not mess up order of operations:
int x = TIMES_TWO(1 - 5);
Without the brackets it'd show up as this:
int x = 1 - 5 * 2;
Which evaluates to 1 - 10 which is not what you want.
There's an art to using #define effectively to hide otherwise ugly implementation details. The name ol_parser_parse isn't something you need to worry about if you can use the yyparser macro. That gives the implementers the freedom to rename that function and the corresponding macro without breaking all your code.

Related

How to pass string as prefix of defined macro

Is there any idea to pass C string as part of the defined macro like below code?
#define AAA_NUM 10
#define BBB_NUM 20
#define PREFIX_NUM(string) string##_NUM
int main()
{
char *name_a = "AAA";
char *name_b = "AAA";
printf("AAA_NUM: %d\n", PREFIX_NUM(name_a));
printf("BBB_NUM: %d\n", PREFIX_NUM(name_b));
return 0;
}
Expected output
AAA_NUM: 10
BBB_NUM: 20
As mentioned in other posts, you can't use run-time variables in the pre-processor. You could however create enum that way. Though it is usually not a good idea to generate identifiers with macros either, save for special cases like when maintaining an existing code base and you are limited in how much of the existing code you can/want to change. So it should be used as a last resort only.
The least bad way to write such macros would be by using a common design pattern called "X macros". These are used when it is important that code repetition should be reduced to a single place in the project. They tend to make the code look rather alien though... Example:
#define PREFIX_LIST(X) \
/* pre val */ \
X(AAA, 10) \
X(BBB, 20) \
X(CCC, 30) \
enum // used to generate constants like AAA_NUM = 10,
{
#define PREFIX_ENUMS(pre, val) pre##_NUM = (val),
PREFIX_LIST(PREFIX_ENUMS)
};
#include <stdio.h>
int main (void)
{
// one way to print
#define prefix_to_val(pre) pre##_NUM
printf("AAA_NUM: %d\n", prefix_to_val(AAA));
printf("BBB_NUM: %d\n", prefix_to_val(BBB));
// another alternative
#define STR(s) #s
#define print_all_prefixes(pre, val) printf("%s: %d\n", STR(pre##_NUM), val);
PREFIX_LIST(print_all_prefixes)
return 0;
}
A macro is only processed before compilation and not at runtime. Your code example does not work as you can see here.
Good practice (for example MISRA coding rules) recommend to use macros as little as possible since it is error prone.
Preprocessor works at compile time and here name_a and name_b are non constant, and even if they were (i.e. const char *str is a real constant in C++ but not in C), there is a literal substitution and the preprocessor does not know the contents of variables.
This works (notice that the parameter should be expanded by another macro in order to get a valid token):
#include <stdio.h>
#define AAA_NUM 10
#define BBB_NUM 20
#define _PREFIX_NUM(string) string##_NUM
#define PREFIX_NUM(string) _PREFIX_NUM(string)
int main(void)
{
#define name_a AAA
#define name_b BBB
printf("AAA_NUM: %d\n", PREFIX_NUM(name_a));
printf("BBB_NUM: %d\n", PREFIX_NUM(name_b));
return 0;
}
There is no way in C to create runtime symbols and use them. C is a compiled language and all symbols have to be known before the compilation.
The preprocessor (which do changes on the text level before the compilation) does not know anything about the C language.

Is there a way to expand macro based on command line arguments? [duplicate]

Following program compiles successfully and print 1000 without even calling a foo() function from our main() function. How is it possible?
#include<stdio.h>
void foo()
{
#define ans 1000
}
int main() {
printf("%d", ans);
return 0;
}
#defineis run by the preprocessor which is staged before the compiler. After the preprocessor is done, the code will look like this:
/* Everything that is inside stdio.h is inserted here */
void foo()
{
}
int main() {
printf("%d", 1000);
return 0;
}
And this is what actually get compiled.
The preprocessor is very important to make header files work. In them, you see this structure:
#ifndef foo
#define foo
/* The content of the header file */
#endif
Without this, the compiler would complain if a header file is included more than once. You may ask why you would want to include a header file more than once. Well, header files can include other header files. Consider this macro, which is useful for debugging. It prints the name of the variable and then the value. Note that you would have to do a separate version for different types.
#define dbg_print_int(x) fprintf(stderr, "%s = %d", #x, x)
This is pretty versatile, so you may want to include it in a header file for own use. Since it requires stdio.h, we include it.
/* debug.h */
#include <stdio.h>
#define dbg_print_int(x) fprintf(stderr, "%s = %d", #x, x)
What happens when you include this file and also include stdio.h in you main program? Well, stdio.h will be included twice. That's why debug.h should look like this:
/* debug.h */
#ifndef DEBUG_H
#define DEBUG_H
#include <stdio.h>
#define dbg_print_int(x) fprintf(stderr, "%s = %d", #x, x)
#endif
The file stdio.h has the same construct. The main thing here is that this is run before the compiler. The define is a simple replacement command. It does not know anything about scope or types. However, as you can see here, there is some basic logic built into it. Another thing that the preprocessor does is to remove all the comments.
You can read more about the C preprocessor here: http://www.tutorialspoint.com/cprogramming/c_preprocessors.htm
The #define is processed by the preprocessor before the compiler does anything. It is a simple text replacement. The preprocessor doesn't even know if the line of code is inside or outside a function, class or whatever [Ref: https://stackoverflow.com/a/36968600/5505997]. Clearly you do not need to call the function to set the value and obviously you will not get any error during compile.
As others have stated, #define is a preprocessor directive, not C source code. See Wiki here.
Point being, in your code #define ans 1000 is not a variable definition, meaning that even if you were calling foo() in the main, you would still not be setting "ans" at runtime, because it is simply not a variable. It is just telling the preprocessor what to do with the "label" "ans", when it finds it in your source code.
In this example, the main() will essentially be calling an empty foo() function:
int main()
{
foo(); // Calls an empty function
printf("%d", ans); // ans will have been substituted by 1000 by the time you start executing you code
return 0;
}
The definition of "ans" will simpy not exist anymore by the time you start executing you main(). This is what the preprocessor does (in part). It finds all the #defines declared in your entire source code and tries to find places in your code where you have used these defines. If you have not used them, it moves on (don't care), if you have, it substitutes the label by the actual defined value.

adding a statement after or before all specific function calls using define in C

I have done this before but somehow I can't do it now so I ask here.
I have some codes I downloaded from a git repository and I want to print the filename, and linenumber whenever malloc is called. I made a simple test.
---- test.c ----
#include <stdlib.h>
#include <stdio.h>
#include "xxx.h"
main()
{
printf("hello\n");
int *ip = malloc(120*sizeof(int));
printf("ip = %x\n",ip);
free(ip);
}
---- xxx.h
#define malloc(x) do {malloc(x); \
printf("malloc at %s()-%d,%s\n",__func__,__LINE__,__FILE__);} \
while(0)
When I do gcc test.c, I get
test.c: In function 'main':
test.c:8: error: expected expression before 'do'
How should I fix xxx.h ? (this question applies also for C++)
Try this:
#define malloc(x) ( \
printf("malloc at %s()-%d,%s\n",__func__,__LINE__,__FILE__), \
malloc(x))
The idea is to use the "comma operator" like this:
int *ip = (printf(...), malloc(120*sizeof(int)));
The result of the comma operator is always its last argument.
Given the macro, the line
int *ip = malloc(120*sizeof(int));
expands to
int *ip = do { malloc(120*sizeof(int)); printf("malloc at %s()-%d,%s\n",__func__,__LINE__,__FILE__);} while(0);
which hopefully makes it obvious where that error comes from.
John Zwinck's solution is a good option, although personally I'd create a wrapper function (named something other than malloc, naturally) rather than a macro.

Can preprocessor directive #include be disabled/excluded?

For example: If I have two .h files
process1.h and process2.h
and they contain two function with different output variables.
process1.h:
function(int var)
{
return 2*var;
}
process2.h:
function(int var)
{
return 10*var;
}
Can this be done in main.c:
int main()
{
int a = 2;
#include "process1.h"
printf("%d",function(a)); //output is 4
EXCLUDE #INCLUDE "process1.h" ????? <----can this be done in any way??
#include "process2.h"
printf("%d",function(a)); //output is 20
}
No, you cannot "un-include" a file. Think of all the preprocessor directives (lines starting with #) as happening before the actual C compiler even sees the source file. They just operate on the text of the file, and the preprocessor could be implemented as a separate step that just feeds new text into the actual compiler.
The best way to modify the actions of an include depending on the caller is to use further macros inside the included files, that you can #define before including them.
Still, your overall syntax is off, you can't (typically) nest functions in C.
No, and you should not try to write a program with two functions of the same name.
In the special case that the functions are actually defined in the header file (instead of just prototypes), you can do this:
#define function function_file1
#include "file1.h"
#undef function
#define function function_file2
#include "file2.h"
#undef function
int
main (void)
{
int a = 2;
printf ("%d\n", function_file1 (a));
printf ("%d\n", function_file2 (a));
}
BUT if you rename a function prototype then you haven't actually renamed the real function, so you'll get undefined symbol error when you link.
In any case, if you have two functions defined with the same name then it won't link anyway, not matter what else you do in the sources. (In C++, it is sometimes possible to define two things with the same name, but the One-Definition-Rule means the linker is allowed to assume they are both the same thing really and just pick one.)
This is why libraries are supposed to use names that won't be used elsewhere - usually by adding a common prefix to all symbol names (e.g. my_unique_lib_initialize()).
Why not use array of function pointers. Sure you need to initialize it at the start but I think it probably solves what you want to do.
int process1_function(int var);
int process2_function(int var);
int main(void)
{
int i, a = 10;
int (* functions[2])(int);
functions[0] = process1_function;
functions[1] = process2_function;
for(i=0; i < 2; i++)
{
printf("%d", (functions[i])(a));
}
return 0;
}
If you do not need to dynamically change which function you're going to call you can also just prefix the functions:
int process1_function(int var);
int process2_function(int var);
int main(void)
{
printf("%d",process1_function(a));
printf("%d",process2_function(a));
return 0;
}

what is the use of int i()

#include <stdio.h>
#define main() main(){printf("hi");}int i()
main()
{//empty main
}
what is the use of int i()
That's a pretty silly program, but the purpose of the int i() is so that it will compile - the braces at the end:
{//empty main
}
will cause an error if there isn't a function declaration included in the #define statement. If I delete it, gcc gives the error:
testfile.c:4: error: expected identifier or ‘(’ before ‘{’ token
You can use the -E flag to gcc to see why the int i() is necessary - it will show you the output of the preprocessor without compiling.
Think about what you get if you expand the macro main() in the program:
#include <stdio.h>
main(){printf("hi");}int i()
{//empty main
}
The int i() is needed there to make the remaining { ... } part of a syntactically valid function definition.
As for intention, I can only guess that the point of the macro is to replace the existing main with a stub one. It's a bit icky IMO.
In that code main() will be expanded and the result will end with
int i()
{//empty main
}
what is the use of int i()
It makes the output of a very strange and broken macro compilable

Resources