I' m learning Macro in c,
I wrote a small function in macro to swap number, but passed the value as 'pass by value' since i didn't use address of operator (&) before the variable in the argument, But when i ran the program. The value got swaped. You can refer the code and mention me where i got wrong in understanding?
#include<stdio.h>
#include<conio.h>
#define swap(a,b) a = a+b;b = a-b; a = a-b;
int main()
{
int x = 5, y = 10;
swap(x,y);
printf("%d %d\n",x,y);
getch();
return 0;
}
Do the arguments acts as pass by reference, when using it in macro?
C doesn't have pass-by-reference. And that's not what's happening here anyway. When a macro is "called", the preprocessor replaces the call-site with the body.
With your example, the invocation
swap(x,y);
is replaced by
x = x+y;y = x-y; x = x-y;;
This last line is what the actual parser of the compiler sees.
Many compilers have options to stop after the preprocessing step. I suggest you use that to see exactly what the preprocessor have done.
I also hope you start to see how macros can "break" your code.
For example if the code was
if (some_condition)
swap(x,y);
Then it would be expanded to (with some reformatting)
if (some_condition)
x = x+y;
y = x-y;
x = x-y;
;
This is clearly not what was intended and will not work.
You also have the case when the arguments to the macro are not simple variables, but expressions. Like
swap(x+1,y*2)
While would be replaced by
x+1 = x+1+y*2;y*2 = x+1-y*2; x+1 = x+1-y*2;;
This also would not work.
Related
Let's assume we have the following code in a language that looks a lot like C.
int A[2];
A[0]=4;
A[1]=7;
void f(int x, int y) {
x++; A[1]++; y++;
printf(x, y, A[0], A[1]);
}
void main() {
int k = 0;
f(k, A[k]);
print(k, A[0], A[1]);
}
I want to define the output of this program.
I haven't understood well the difference between the call-by-name and the call-by-macro-expansion method.
So, in the call-by-name method, k is initialized to 0 and then f() function is called. x becomes equal to "k" and y becomes equal to "A[k]". The first command in the called function is x++ which increases the value of "k" by 1. So k becomes equal to 1. Then A[1] is increased, so A[1] becomes 7+1=8. None of the x,y are affected. Finally, we have the command y++ which increases the value of "A[k]" by 1, so it increases the value of A[1] (since now k=1) by 1, so A[1] becomes now 8+1=9.
Then f() prints: 1,9,4,9
And then we return to the main() fuction which prints: 1,4,9
So, the output of the program is 1,9,4,9,1,4,9 if I am not mistaken.
But how does call-by-macro-expansion differs from this method? What does it change?
There is nothing like "call-by-macro" in C language. There are only macros which take parameters. Macros are just textually replaced by the preprocessed tokens.
IMO macros should be used only if they are really needed, in most cases it better to use inline functions. Macros are dificult to debus (as compiler compiles the preprocessed .c file) and error prone.
Example
#define SUB(a,b) a-b
and the usage
printf("%d", SUB(3-2,4-5));
the result will not be 2 only -8
But how does call-by-macro-expansion differs from this method? What does it change?
For C, "call-by-macro-expansion" doesn't exist. Instead, for macros the preprocessor does a glorified "cut&paste" operation on raw text.
For example, if you have this:
int A[2];
A[0]=4;
A[1]=7;
#define MACRO(x, y) { \
x++; A[1]++; y++; \
printf(x, y, A[0], A[1]); \
}
void main() {
int k = 0;
MACRO(k, A[k]);
print(k, A[0], A[1]);
}
Then the preprocessor will cut&paste the text from the macro to where the macro is used and then replace x and y with the arguments you provided, so that (after preprocessing) the source code looks like this:
int A[2];
A[0]=4;
A[1]=7;
void main() {
int k = 0;
{ \
k++; A[1]++; A[k]++; \
printf(k, A[k], A[0], A[1]); \
}
print(k, A[0], A[1]);
}
Of course the macros don't need to contain valid code, and the source doesn't even need to be C at all (e.g. you could use the preprocessor to preprocess assembly language source code by telling the compiler "don't compile, just output the preprocessed text"); and there's no real reason why you can't use a completely different preprocessor (with completely different features and/or macro syntax) and feed the resulting text into a C compiler (telling the compiler "don't preprocesses, just compile").
In practice; the main differences for macros and functions are:
for macros, there's no type-checking on the parameters, so bugs end up being more annoying to find
for macros, a debugger will only say the line number where the macro was expanded and won't say where the code actually came from, so bugs end up being more annoying to find
for macros, because they don't have to be valid C you can do some bizarre shenanigans (e.g. #define forever while(1) { so you can use forever i++; } as an infinite loop), and can be powerful for code obfuscation (deliberately making it hard to read the code).
for functions, the compiler can decide not to inline the function to reduce code size
for functions, you can have recursion (with macros you can't - it'd end up being an infinite amount of text)
for functions, you can have function pointers and/or have external functions (where the linker figures out where the function is, either with static linking or dynamic linking).
For a simpler example of (a) difference, consider this code:
#define f(x) { \
x++; \
}
void g(int x) {
x++;
}
void main() {
int a = 1;
int b = 1;
f(a);
printf("%d\n", a);
g(b);
printf("%d\n", b);
}
These look the same, but are not. After expanding the macro and inlining the function, it becomes more like this:
void main() {
int a = 1;
int b = 1;
a++;
printf("%d\n", a); // Will print "2' because the original `a` was changed
int x = b;
x++;
printf("%d\n", b); // Will print "1' because the original `b` was not changed
}
Note that this is exactly the same problem with the example above (for the macro, the x++; modifies the original k and not a copy of the original k; and for the function the x++; modifies a copy and not the original).
I was wondering if printf() in C or C++ programming language returns the number of characters printed on screen, then how does
printf("%d", 10);
work? Why doesn't it show any error(s)?
Rather an integer variable should be used to catch the returned value, as follows:
int var = printf("%d", 10);
How does printf() work internally to resolve this?
printf() does nothing special here. C doesn't require you to do anything with the result of expressions you evaluate.
2 + 3;
is a perfectly valid statement. (It may generate a warning from your compiler because it doesn't actually do anything, unlike a function call such as printf().)
Let's look at a slight variation of your second version:
int var;
var = printf("%d", 10);
Here you might think we're "catching" the return value from printf in var, so there's no result value being left lying around. But = is just another operator (like + or &&) and it returns a value!
int x, y, z;
x = (y = (z = 42)); // perfectly valid code
x = y = z = 42; // same thing; = is right associative
= returns the value being assigned and this code sets all three variables to 42.
So if C were to require you to "catch" return values, you couldn't use assignment statements because they also return a value.
i have this c macro code :
#define d(x, y, z) ( \
x += z, \
y += x, \
x += y \
)
I have several questions :
Does this macro function return something ? (e.g. return x, y, or z)
or is it just add the parameter variable with itself ? (which is
useless, i think).
What does the \ means ?
Why does the original coder use comma-operator after each operation ? Why not just use ; instead of , ?
Any help would be appreciated
Does this macro function return something ? (e.g. return x, y, or z) or is it just add the parameter variable with itself ? (which is useless, i think).
It modifies the value of the variables. The "return" value is the final value of x.
What does the \ means ?
When placed last on a line, it negates the newline so that the macro definition can span more than one line.
Why does the original coder use comma-operator after each operation? Why not just use ; instead of `, ?
Macros replace text. Consider the following code:
int x=1, y=2, z=3, f;
f = 3 * (d(x,y,z));
If the macro uses comma, the code becomes:
int x=1, y=2, z=3, f;
f = 3 * (x+=z, y+=x, x+=y); // Evaluates to 3 * (the final value of x)
If the macro uses semicolon, the code becomes:
int x=1, y=2, z=3, f;
f = 3 * (x+=z; y+=x; x+=y); // Syntax error!!!
1) The macro does not return anything itself. It is just a dumb piece of code substituted literally by the preprocessor wherever it encounters it. It can be any kind of text.
2) \ is used for letting the preprocessor know that the current macro also expands over the next line. (multi-line macro)
3) I cannot make any assumption about the original coder's intentions. However by using the comma operator in there the whole macro becomes a C language expression. For example running something like this works (it wouldn't if semicolons were in there):
int a = 0;
int x = 1;
int y = 2;
int z = 3;
a = d(x, y, z);
printf("a = %d\n", a);
printf("x = %d\n", x);
printf("y = %d\n", y);
printf("z = %d\n", z);
and prints:
a = 10
x = 10
y = 6
z = 3
First and foremost #define is a Preprocessor Directive, which means when the source code/c code is complied the #define replaces LHS with RHS - meaning whereever the d(x,y,z) is used will be replaced with the equation given
for example the below c code will print - modified a = 9, b=8, c=9
#define d(x,y,z) \
x+=1, \
y+=2, \
z+=3
#include <stdio.h>
int main()
{
unsigned int a,b,c;
a=5;
b=6;
c=7;
printf("modified a = %d, b=%d, c=%d \n",d(a,b,c));
}
basically what happened here is d(a,b,c) - is replaced with a+=1,b+=2,c+=3
The meaning of \ is that the pre-processor directive continues in the next line.
As for as the comma-operator is concerned we need to look at source code to see where exactly it is used. as you can see in the above code the comma operator actually separates all the three variables and is able to print properly - if in case i replace comma with any other operator we will get compilation error.
Hope this answers your questions :)
Regards
Hari
I have a simple program to calculate the volume of a cube. It runs fine, but the result I get is wrong. It comes out as "Y is 392". Can anyone help me understand why it is 392? I have just begun C, so I do not understand all of the code.
I realise this Macro is badly written, I am just trying to understand its behavior before I rewrite it.
#define CUBE(x) (x*x*x)
void main(void);
void main(void){
int x, y;
x = 5;
y = CUBE(++x);
printf("Y is %d \n", y);
}
This is because the macro expands to:
y = ++x * ++x * ++x;
This is a very badly written macro, for this very reason; it looks like a function call (which would evaluate the argument only once) but it really evaluates it three times.
This gives undefined behavior since there is a lack of sequence points.
The reason this happens is that the macro pre-processor substitutes the parameters as they are. So, CUBE(++x) is expanded to:
++x*++x*++x
You should avoid using expressions with side effects in macros because of this.
#include<stdio.h>
#include<conio.h>
#define PROD(x) (x*x)
void main()
{
clrscr();
int p=3,k;
k=PROD(p+1); //here i think value 3+1=4 would be passed to macro
printf("\n%d",k);
getch();
}
In my opinion, the output should be 16, but I get 7.
Can anyone please tell me why?
Macros are expanded, they don't have values passed to them. Have look what your macro expands to in the statement that assigns to k.
k=(p+1*p+1);
Prefer functions to macros, if you have to use a macro the minimum you should do is to fully parenthesise the parameters. Note that even this has potential surprises if users use it with expressions that have side effects.
#define PROD(x) ((x)*(x))
The preprocessor expands PROD(p+1) as follows:
k = (p+1*p+1);
With p=3, this gives: 3+1*3+1 = 7.
You should have written your #define as follows:
#define PROD(x) ((x)*(x))
The problem here is that PROD is a macro and will not behave exactly like you intend it to. Hence, it will look like this:
k = p+1*p+1
Which of course means you have:
k = 3+1*3+1 = 7
#define PROD(x) (x*x)
PROD(3+1) is changed by the preprocessor to 3+1*3+1
macro are not function . These are replaced by name
It will be p+1*p+1
This is what compiler is going to see after preprocessors does its job: k= p+1*p+1. When p = 3, this is evaluated as k = 3+(1*3)+1. Hence 7.
This is exactly why you should use functions instead of macros. A function only evaluates each parameter once. Why not try
int prod(int x)
{ return x * x; }
and see the difference!