void fun()
{
// Essentially this is a function with an empty body
// And I don't care about () in a macro
// Because this is evil, regardless
#define printf(a, b) (printf)(a, b*2)
}
void main() // I know this is not a valid main() signature
{
int x = 20;
fun();
x = 10;
printf("%d", x);
}
I am having doubt with #define line ! Can you please give me some links documentation for understanding this line of code.Answer is 20.
The #define defines a preprocessor macro is processed by the preprocessor before the compiler does anything.
The preprocessor doesn't even know if the line of code is inside or outside a function.
Generally macros are defined after inclusion of header files.
i.e. after #include statements.
Preprocessor macros are not part of the actual C language, handling of macros and other preprocessor directives is a separate step done before the compiler1. This means that macros do not follow the rules of C, especially in regards to scoping, macros are always "global".
That means the printf function you think you call in the main function is not actually the printf function, it's the printf macro.
The code you show will look like this after preprocessing (and removal of comments):
void fun()
{
}
void main()
{
int x = 20;
fun();
x = 10;
(printf)("%d", x*2);
}
What happens is that the invocation of the printf macro is replaced with a call to the printf function. And since the second argument of the macro is multiplied by two, the output will be 10 * 2 which is 20.
This program illustrates a major problem with macros: It's to easy to a program look like a normal program, but it does something unexpected. It's simple to define a macro true that actually evaluates to false, and the opposite, changing the meaning of comparisons against true or false completely. The only thing you should learn from an example like this is how bad macros are, and that you should never try to use macros to "redefine" the language or standard functions. When used sparingly and well macros are good and will make programming in C easier. Used wrongly, like in this example, and they will make the code unreadable and unmaintainable.
1 The preprocessor used to be a separate program that ran before the compiler program. Modern compilers have the preprocessor step built-in, but it's still a separate step before the actual C-code is parsed.
Let me put this in another way.
printf() is an inbuilt standard library function that sends formatted output to stdout (Your console screen). The printf() function call is executed during the runtime of the program. The syntax looks likes this.
int printf(const char *format, ...)
But this program of yours replaces the printf() function with your macro before the compilation.
void fun(){
#define printf(a, b) printf(a, b*2)
}
void main() {
int x = 20;
fun();
x = 10;
printf("%d", x);
}
So what happens is, before compilation the compiler replaces the inbuilt function call with your own user defined macro function with two arguments:
a="%d" the format specifier and
b=the value of x =10.
So the value of x*2 =20
Related
From what I understand about macros in C, they are predefined constants that will be used throughout the program with their constant value, so we go ahead and define them to avoid further complications and make the code more readable, so people reading it will understand what is supposed to stay constant and what isn't.
I have read here and there (C programming A Modern Approach, K.N King) that we can define these two functions as macro.
Since I'm somewhat new to C, I can't wrap my head around how can these two be defined as macro?
There are two types of macros: simple substitution macros and function-like macros.
Substitution macros replace one instance of a symbol with another. For example:
#define LEN 10
char str[LEN];
After preprocessing, this becomes:
char str[10];
A function-like macro can take parameters that can be plugged in to whatever gets substituted:
#define MAX(a,b) ((a) > (b) ? (a) : (b))
int x = MAX(2,3);
After preprocessing:
int x = ((2) > (3) ? (2) : (3));
In the case of getchar and putchar, they can be defined as follows:
#define getchar() getc(stdin)
#define putchar(c) putc(c, stdout)
There are basically three types of preprocessor macros:
Simple defined without any value. For example
#define THIS_IS_A_MACRO
This kind of macros are used for conditional compilation.
Symbolic constants. For example
#define SOME_SYMBOLIC_CONSTANT 123
These kind of macros are what you're thinking of.
Function-like macros. Foe example
#define SOME_MACRO(a_macro_argument) printf("Macro invoked with argument %d\n", a_macro_argument)
This kind of macro is used very much like functions, but are replaced by the preprocessor in the source code before the compiler parser sees the code, with the macro arguments replaced with their actual values.
Lets take the function-like macro and how it will be expanded by the preprocessor:
SOME_MACRO(123);
The above will be replaced like
printf("Macro invoked with argument %d\n", 123);
Fully depends on implementation. They can be function also.
Standards don't demand anything explicit about the type of implementation. But you can check here it points Any function declared in a header may be additionally implemented.... as pointed by Eugene.Sh
To say it more clearly, there may be a function in the library or it can be a macro also (for getchar). Classically, the macro for getchar() would be #define getchar() getc(stdin), and getc() might also be a macro.
Standard says that The getc function is equivalent to fgetc, except that if it is implemented as a macro, it may evaluate stream more than once, so the argument should never be an expression with side effects.
Now it boilds down to fgetc in which case we know that it is guaranteed to be a function. Thread safety makes it more likely to be a function.
Thus, in C++, never define getchar and putchar as member functions of a class. In case, they are defined as macros in stdio.h file, the compiler would throw all sorts of strange errors.
#include <stdio.h>
class My_IO_Device
{
int putchar (int c); // seemingly innocent
};
I do not know whether <cstdio> guarantees them to be implemented as functions.
I'm trying to explain this satisfactorily, but when I call a function I want it to virtually insert itself into the main function's code in the place where I call it, so I can save typing it out multiple times, however it directly affects variables defined in the scope of the main function. What's the best way to achieve this?
EDIT: I should probably make it clear I also want it to take a single argument.
Sounds like you need a preprocessor macro. These aren't real functions, but blocks of code the the preprocessor replaces before compiling the code. E.g., consider a simple macro to increment a number:
#include <stdio.h>
#define INC(x) (x)++
int main() {
int a = 1;
INC(a);
INC(a);
printf("%d\n", a);
return 0;
}
The text INC(a) will be replaced with a++, so running this program will print out 3 (1 after two increments).
Trying to figure out something simple in a C macro,
like this code for example:
#include <stdio.h>
#define MACRO(b) printf("%d\n", b*b)
int main()
{
MACRO(4+1);
}
The output for this code is 9, I think that it should be 25.
I don't have any idea why and how the result for this is 9 and not 25.
When you use the macro, the preprocessor replaces it and its arguments quite verbatim, so the macro expansion in your code will look like
printf("%d\n", 4+1*4.1);
That will not provide you with the result you want, and it is one of the reasons that function-like macros are looked down upon.
You need to use parentheses to make sure this problem doesn't occur:
#define MACRO(b) printf("%d\n", (b)*(b))
while will then result in the following expansion:
printf("%d\n", (4+1)*(4.1));
Whenever you have problems with something preprocessor related, there are options for just about all compilers to stop after the preprocessing stage, which allows you to look at the preprocessed source and which will help you with problems like this.
Also note that another possible problem here is if the expression you pass as argument to the macro is e.g. a function call with some side-effect that function will be called twice and the side-effect will be happen twice, even when using parentheses.
A simple example, using your macro:
int my_function(void)
{
printf("Foo\n");
return 1;
}
int main(void)
{
MACRO(my_function());
}
The above program will print "Foo\n" twice. If MACRO was a proper function the call to my_function would only happen once and the printout from the function would only happen once.
Put parentheses around your macro to evaluate arguments in the correct order:
#include <stdio.h>
#define MACRO(b) printf("%d\n", (b)*(b))
int main()
{
MACRO(4+1);
}
I have encountered the following debug macro in an embedded device codebase:
extern void DebugPrint(uint8_t *s);
#define DEBUG_MSG(x) do { PRINT_CURRENT_TIME; \
DebugPrint x ; } while(0)
Since there are no parentheses around x in the macro body (at the DebugPrint x part), all calls to this macro (all over the codebase) add another set of parentheses around strings:
DEBUG_MSG(("some debug text"));
Is there any reason to do this? Does it simplify optimizing away these calls in release builds, or something like that? Or is it just plain nonsense?
I thought perhaps there would be additional overloads of DebugPrint with more arguments, but there are none.
Here's a theory:
The preprocessor parses the arguments of a macro expansion in a way that mimics the compiler's expression parsing. In particular it parses terms in parentheses as a single argument.
So the DEBUG_MSG author's intention might have been to enforce the use of parentheses.
This might make sense when the DebugPrint print function would actually be a printf style variadic function. You could call the function with a single string literal or with a variable number of arguments:
DEBUG_MSG(("reached this point in code"));
DEBUG_MSG(("value of x = %i", x));
But this is pure speculation. Can't you just ask the author?
I believe that no. Macros are replaced by the compiler, so they have nothing to do with execution speeds. This:
#define MACRO(x) do_something(x)
MACRO("test");
Is no different than this
#define MACRO(x) do_something x
MACRO(("test"));
Since the compiler will replace them both with the same output:
do_something("test");
which will then compile to produce the same object code.
I would like to create two macros. One of them will expand to function prototype and function content and the other one will expand to only function prototype. I'm thinking to create followings:
#ifdef SOME_CONDITION
#define MY_MACRO(prototype, content) prototype;
#else
#define MY_MACRO(prototype, content) prototype content
#endif
As an example usage
MY_MACRO(int foo(int a, int b)
,
{
return a + b;
}
)
These macros seems working fine. Do you think are those macros safe enough so that they will work for every kind of C code as intended? Or do you see any pitfall?
The first major pitfall, it doesn't work. When the second macro is used, it creates
int foo(int a, int b), { return a + b; }
which is not a valid function definition. To fix this, you must remove the , in the macro definition.
The second pitfall I see, usually C programmers don't use such fancy macros. It's simply confusing, when you're used to reading C source code.
If you're worried about diverging prototype declarations and corresponding function definitions, I suggest using appropriate compiler flags or tools. See this question and answers, How to find C functions without a prototype?
There are a lot of pitfalls, it is simply too naive, I think.
never have macros that change the grammatical parsing, here in particular that add a ; at the end. Nobody will be able to comprehend code like that that has function-like macros invocations in file scope without a terminating semicolon.
your macro expects two arguments, exactly. If your code block in the second argument contains an unprotected , operator, you are screwed.
Your second variant should definitively not have a , on the right hand side.
This would work a bit better
#ifdef SOME_CONDITION
#define MY_MACRO(prototype, ...) prototype
#else
#define MY_MACRO(prototype, ...) prototype __VA_ARGS__ extern double dummyForMY_MACRO[]
#endif
you'd have to use that as
MY_MACRO(int foo(int a, int b), { return a + b; });
So this provides at least something visually more close to C code (well...) and handles the problem of the intermediate commas. The unused variable dummyForMY_MACRO should cause no harm, but "eats" the ; in the second form.
Not that I'd suggest that you use such a thing untested like this.
Do you think are those macros safe enough so that they will work for every kind of C code as intended? Or do you see any pitfall?
Do not attempt to re-invent the C language. The people who read your code will be other C programmers. You can expect them to know C. You cannot expect them to know "the-home-brewed-garage-hacker-macro-language".
Strive to write code that is as simple as readable as possible. Avoid complexity, avoid confusion. Don't attempt to create solutions when there exists no problem to solve.
I actually did something similar quite recently and learned the pitfalls of passing in code as a macro argument.
For example try this seemingly correct code (using the first macro definition):
MY_MACRO(int foo(int a, int b)
,
{
int c = 1, d = 2;
return a + b + c + d;
}
)
You'll most likely see a compile error something to the tune of the macro expecting only 2 arguments while you provided 3.
What happens is that the macros are compiled by the pre-processor which doesn't care about C syntax. So in it's eyes, each , is a argument separator. So it thinks that the first argument to the macro is int foo(int a, int b), the second argument { int c = 1 and the third argument as d = 2; return a + b + c + d; }.
So basically, the moral of the story is that "never pass in code as argument". Most macros that want to be flexible code-wise compile down into a if or a for statement (e.g. list_for_each in http://lxr.free-electrons.com/source/include/linux/list.h#L407).
I'd suggest that you stick to standard #ifdefery in your situation. e.g.
#ifndef UNIT_TEST
int foo(...) {
//actual implementation
}
#else
int foo(..) {
return 0;
}
#endif
This sort of code is fairly standard: http://lxr.missinglinkelectronics.com/#linux+v3.13/include/linux/of.h (search for CONFIG_OF)
Find below example which helps you to fulfils both of your requirements:
#ifdef SOME_CONDITION
#define MY_MACRO(a, b) \
int foo(int a, int b);
#else
#define MY_MACRO(a, b) \
int foo(int a, int b) \
{\
return 0;\
}
#endif
You can use 1st macro by MY_MACRO(a, b) and 2nd macro as MY_MACRO(a, b);