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.
Related
Please give me full description....
The first snippet of code has the 'function call' (macro invocation) before the increment operator, and second one has the function call after the increment operator.
#include <stdio.h>
#define square(x) x*x
int main()
{
int a,b=3;
a=square (b)++;
printf("%d%d",a,b);
return 0;
}
output:
124
why is 124 returned here
#include <stdio.h>
#define square(x) x*x
int main()
{
int a,b=3;
a=square (b++);
printf("%d%d",a,b);
return 0;
}
output:
125
and 125 here?
The thing to keep in mind is that macros provide simple substitution of preprocessor tokens. In particular, they may evaluate their arguments more than once, and if not guarded by parentheses, they may produce unintended reassociation.
In the first example, we have
a=square (b)++;
This expands to:
a=b*b++;
This is actually undefined behavior, since the b and b++ are unsequenced, and b++ modifies b. In your case, you are seeing 12 and 4 for a and b, so it would seem that the first value of b is picking up the incremented value, so you're getting 4*3, but you can't count on this behavior. The final value of b is 4 since it is incremented once.
In the second example, we have:
a=square (b++);
This expands to:
a=b++*b++;
This is again undefined behavior. In your case, it appears that you're getting 4*3 (or 3*4), but again, you can't count on this behavior. The final value of b is 5 since it is incremented twice, but this too is undefined behavior.
In addition to Tom's answer, which explains what is happening, here is an example of how you could define a macro for squaring a number safely:
#define SQR(x) ( \
{ \
__auto_type x_ = (x); \
\
x_ * x_; \
} \
)
It only has an appearance of x, and therefore it doesn't evaluate it twice. The copy x_ is used instead. Note that variables created in a macro may conflict with other variables created in the function that calls the macro. To avoid name collisions you use special names that shouldn't be used in normal code such as a trailing _.
With this macro, this:
a = SQR(b++);
will be equivalent to this:
a = SQR(b);
b++;
Warning: This works on some compilers as an extension (GCC for example), but it is not standard C.
Another option, if you want standard C, is to use an inline function. It is ok if you want it to work on just one type (there is _Generic in C11, but I never used it, so no idea).
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.
I have a basic code to learn function call. But I did not understand something in this code. I got confused when I compare to with my answer and expected output.
My code is below:
#include <stdio.h>
void f(int a, int b, double c){
printf("%d \n", a);printf("%d \n", b);printf("%f \n", c);
}
int main(void){
int i = 0, x = 7;
float a = 2.25;
f (x=5, x-7, a);
printf("\n\n");
f (x = 6, x-7, a);
printf("\n\n");
printf("%d %d\n",i, i++ );
printf("%d %d\n",i, ++i );
return 0;
}
At the last 2 printf statements, My answer was as:
0 0
1 1
But the output as:
1 0
2 2
Can you explain why?
It is undefined behavior in C. It may vary as per the execution or many other things. The order of evaluation of function arguments are unspecified. You can never explain the behavior you see by any standard rule. It would have given different result when you run it in front of teacher in a different machine.
Better you write the code which avoids all these sort of ambiguity.
The example which is explicit about this from standard 6.5.2.2p12
In the function call
(*pf[f1()]) (f2(), f3() + f4())
the functions f1, f2, f3, and f4 may be called in any order. All side effects have to be
completed before the function pointed to by pf[f1()] is called.
Same way when you pass the arguments - their evaluation order may vary. And your example of printf is also another such example.
Check the slide from which you got to know about this - must be a slide one Undefined behavior
Can you explain why?
Because the compiler had calculated the arguments from right to left. It was allowed to do it either way, and it finally produced the code which did it like that. You know, it didn't want to die like Buridan's donkey ;-)
You may say that C compilers have no free will. Yes, they don't, but the generated code depends on many different things, such as compiler brand, version, command-line options etc. And C standard doesn't impose any limitations on C compilers in that particular case. So it's officially called "undefined behaviour". Just never do this.
How can we interpret the following program and its success?(Its obvious that there must not be any error message). I mean how does compiler interpret lines 2 and 3 inside main?
#include <stdio.h>
int main()
{
int a,b;
a; //(2)
b; //(3)
return 0;
}
Your
a;
is just an expression statement. As always in C, the full expression in expression statement is evaluated and its result is immediately discarded.
For example, this
a = 2 + 3;
is an expression statement containing full expression a = 2 + 3. That expression evaluates to 5 and also has a side-effect of writing 5 into a. The result is evaluated and discarded.
Expression statement
a;
is treated in the same way, except that is has no side-effects. Since you forgot to initialize your variables, evaluation of the above expression can formally lead to undefined behavior.
Obviously, practical compilers will simply skip such expression statements entirely, since they have no observable behavior.
That's why you should use some compilation warning flags!
-Wall would trigger a "statement with no effect" warning.
If you want to see what the compilation produces, compile using -S.
Try it with your code, with/without -O (optimization) flag...
This is just like you try something like this:
#include <stdio.h>
int main(void){
1;
2;
return 0;
}
As we can see we have here two expressions followed by semicolon (1; and 2;). It is a well formed statement according to the rules of the language.
There is nothing wrong with it, it is just useless.
But if you try to use though statements (a or b) the behavior will be undefined.
Of course that, the compiler will interpret it as a statement with no effect
L.E:
If you run this:
#include <stdio.h>
int main(void){
int a;
int b;
printf("A = %d\n",a);
printf("B = %d\n",b);
if (a < b){
printf("TRUE");
}else{
printf("FALSE");
}
return 0;
}
You wil get:
A = 0
B = 0
FALSE
Because a and b are set to 0;
Sentences in C wich are not control structures (if, switch, for, while, do while) or control statements (break, continue, goto, return) are expressions.
Every expression has a resulting value.
An expression is evaluated for its side effects (change the value of an object, write a file, read volatile objects, and functions doing some of these things).
The final result of such an expression is always discarded.
For example, the function printf() returns an int value, that in general is not used. However this value is produced, and then discarded.
However the function printf() produces side effects, so it has to be processed.
If a sentence has no side effects, then the compiler is free to discard it at all.
I think that for a compiler will not be so hard to check if a sentence has not any side effects. So, what you can expect in this case is that the compiler will choose to do nothing.
Moreover, this will not affect the observable behaviour of the program, so there is no difference in what is obtained in the resulting execution of the program. However, of course, the program will run faster if any computation is ignored at all by the compiler.
Also, note that in some cases the floating point environment can set flags, which are considered side-effects.
The Standard C (C11) says, as part of paragraph 5.1.2.3p.4:
An actual implementation need not evaluate part of an expression if it
can deduce that its value is not used and that no needed side effects
are produced [...]
CONCLUSION: One has to read the documentation of the particular compiler that oneself is using.
I'm attempting to define a macro that allows me to pass in 2 numbers as well as an operator. I want the macro to carry out the specified operation on the two numbers and return the result.
My definition is:
#define GENERAL_OP(x,y,op) ((x) op (y))
which works fine when I call
int result = GENERAL_OP(1, 2, -);
but as soon as I try to pass it a character (which is what I actually need to do in my
generalized function that calls the macro) as in the following example:
void Evaluate(char op)...
int result = GENERAL_OP(1, 2, op);
void Evaluate(char op)...
int result = GENERAL_OP(1, 2, op);
Macro replacement is done before compile time, but the argument of Evaluate is only available at runtime, so the macro expansion leads to
int result = ((1) op (2));
there, and op is not a token that can appear there (probably an undeclared identifier).
Preprocessor operates at compile-time, you can't use the value of op inside your macro.
I see what you're going for... it's sort of like trying to unstringify. I'm pretty sure it can't work the way you want it to. Your best bet would be to do something like:
void Evaluate(char op, int x, int y)
{
int result;
if(op == '-')
GENERAL_OP(x, y, -);
...
But that doesn't make it very "general"...