I am new to C programming, in fact programming at all, and recently learn the use of macros with regard to preprocessor directives. Although I am getting more familiar with it the following exercise that I got from a textbook stumbles me since I do not get the solution or the general "take-away lesson" from it.
Before I wrote this question here, I tried to execute the code myself by adding some printf() in order to obtain the correct answers but it does not even compile. Now, before I write down the question and code I want to make it explicit that this is a self-learning question and that I do not want to offend people here with a question that many will find trivial. I just want to understand what is going on.
The code is as follows
int x=2, y=3, a=4,b=5;
#define MAX(x, y) x > y x : y
int c,d,e,f;
c = MAX( a, 3 );
d = MAX( y, x );
e = MAX( ++x, 1 );
f = MAX( b, MAX (6, 7) );
I am asked to give the values of c,d,e and f. There is an additional hint that although it is named that way the above macro is NOT the maximum operator. Therefore, I don't think the "obvious" guess of e.g. max(a,3) = 4 is correct. Consequently, I don't know what is going on.
EDIT: I forgot to mention: I know that there are parentheses missing for the correct use. But I am specifically asked to evaluate the terms without them. Therefore I am confused since I do not know exactly how the results change and the function behave without those included.
Expanding the macro as-is, we get the following:
Original Expanded
-------- --------
c = MAX( a, 3 ); c = a>3 a : 3;
d = MAX( y, x ); d = y>x y : x;
e = MAX( ++x, 1 ); e = ++x>1 ++x : 1;
f = MAX( b, MAX (6, 7) ); f = b>MAX (6, 7) b : MAX (6, 7);
f = b>6>7 6 : 7 b : 6>7 6 : 7;
Macro expansion is just dumb text substitution - syntax, scope, precedence, associativity, values, side effects, etc., are simply not taken into account when a macro is expanded (macro expansion occurs before the source code is fed to the compiler proper).
Obviously, none of the expanded expressions above will compile. For that to happen, we need to fix the MAX macro by defining it as
#define MAX( x, y ) x>y ? x : y
Now we get the following:
Original Expanded
-------- --------
c = MAX( a, 3 ); c = a>3 ? a : 3;
d = MAX( y, x ); d = y>x ? y : x;
e = MAX( ++x, 1 ); e = ++x>1 ? ++x : 1;
f = MAX( b, MAX (6, 7) ); f = b>MAX (6, 7) ? b : MAX (6, 7);
f = b>6>7 ? 6 : 7 ? b : 6>7 ? 6 : 7;
Better. The expanded expressions above will compile, but the last two don't do anything like what you expect them to. e won't get the max of x and 1, it will either get x+2 or 1 (? introduces a sequence point, so the behavior isn't undefined). f gets ... something, can't remember the associativity of > and ?: offhand, not really willing to dig it up.
Again, macros don't take precedence and associativity into account when expanding their arguments. Imagine we write a macro CUBE that does the following:
#define CUBE(x) x * x * x
and we call it as
y = CUBE( 2 + 3 );
That expands to
y = 2 + 3 * 2 + 3 * 2 + 3;
which gives us the value 17, when we were probably expecting 125.
The right way to define the MAX macro is
#define MAX( x, y ) ((x) > (y) ? (x) : (y))
We not only parenthesize each argument, we parenthesize the entire expression. This way, precedence and associativity are preserved not only if you pass complex expressions as arguments, but also if you pass this macro as an argument to another one (as in the last example):
Original Expanded
-------- --------
c = MAX( a, 3 ); c = ((a) > (3) ? (a) : (3));
d = MAX( y, x ); d = ((y) > (x) ? (y) : (x));
e = MAX( ++x, 1 ); e = ((++x) > (1) ? (++x) : (1));
f = MAX( b, MAX (6, 7) ); f = ((b) > (MAX (6, 7)) ? (b) : (MAX (6, 7)));
f = ((b) > ((6) > (7) ? (6) : (7)) ? (b) : ((6) > (7) ? (6) : (7)));
This time, f will be evaluated like you expect it to be.
The evaluation of e is still problematic (++x can still be evaluated twice). This is a problem in general with macros that expand their arguments more than once - arguments that have side effects can be evaluated multiple times, which will lead to wrong answers or undefined behavior.
Incorrect use of ternary operator.
#define MAX(x,y) x>y x : y
Should be:
#define MAX(x,y) (x>y) ? x : y
And to allow for more complex expressions:
#define MAX(x,y) (((x)>(y)) ? (x) : (y))
You mention that you don't know what is going on. There is only way - run only the preprocessor.
What compiler are you using? Assuming gcc/clang you can -
gcc -E filename.c
This will only run the preprocessor and let you analyze what is going on.
BTW you code doesn't compile because you made a mistake with the ternary operator - should be x > y ? x : y.
Related
I am working on a SQL server project to make conversion between two types of car prices (eg, x is the original price, y is the dealer asking price) based on some rules, so that for every given dealer asking price y, I can get a corresponding original price x. The conversion rule I am having trouble with is this one: x + 5*ceiling(x/100) + some constant c = y, x=?
(It's more of a math problem actually. For example, if the rule is as easy as x + 10 = y, then x = y-10.)
Indeed, it's a math problem, that should be asked on Mathematics Stack Exchange.
That said, note that in the equation x+ceil(x)+c=y, x and y-c differ only by an integer (that depends on x). And since x+ceil(x) is an increasing function of x, if there is a solution it's unique.
Another remark:
for x in (0,1], x+ceil(x) lies in (1,2].
for x in (1,2], x+ceil(x) lies in (3,4].
...
That is, there is a solution only if y-c is in (2n-1,2n] for some integer n. And then, x=y-c-n.
How do we find n? Well, y-c in (2n-1,2n] iff (y-c)/2 in (n-1/2,n]. So we must have n=ceil((y-c)/2).
It's not much more difficult for the equation x+5ceil(x/100)=y-c.
Now,
for x in (0,100], x+5ceil(x/100) in (5,105]
for x in (100,200], x+5ceil(x/100) in (110,210]
...
for x in (100(n-1), 100n], x+5ceil(x/100) in (105n-100,105n]
Again, some values can't be reached, and if there is a solution, it's unique.
And if y-c lies in (105n-100,105n] for some n, then x=y-c-5n.
Of course, you want to find n. Note that y-c in (105n-100,105n] iff (y-c)/105 is in (n-100/105,n], which is a subset of (n-1,n]. So if there is a solution, you must have n=ceil((y-c)/105).
Not a complete answer but for the simple case of
Y = X + Ceiling(X)
declare #X float = 3.7
declare #Y float = 0.0
SELECT #y = #x + ceiling(#x)
SELECT CASE
WHEN (#y -floor(#y)) = 0 THEN #y/2
ELSE (#y - (#y -floor(#y)) - 1)/2 + (#y -floor(#y))
END XValue
This works for all values of X that I've tested. The first case is for when X is a whole integer.
EDIT
For your case of Y = X + 5*CEILING(X)/100 we can surmise that if X is an integer then Y = X + 5/100 * X => 1.05 * X, if X is not an integer then y = X + 5/100(X+1) => 1.05*X + 0.05
So I think the following works for your case:
declare #X float = 3.1
declare #Y float = 0.0
SELECT #y = #x + 5*ceiling(#X)/100
SELECT CASE WHEN (ROUND(#y/1.05,0) = #y/1.05) THEN #y / 1.05
ELSE ROUND((#y - 0.05) / 1.05,2) END
For your case with a constant, I can't see how to solve this without knowing the constant.
I can't get this line to run in constant time on my micro-controller:
int zz,yy; //some binary variables
zz = (yy) ? 0 : (1 & zz);
I tried to change it to
zz = (yy) ? (0 & zz) : (1 & zz);
because & should force an evaluation of the right side even though the left side defines the result as far as I know. But it did not help.
Can anyone suggest me a solution how to make this line constant time?
It entirely depends on your compiler and its settings. Maybe (!yy) *
(1 & zz) helps?
#Quentin
I just started reading C.
Situation :
x = ( y = 3, ( z = ++y + 2 ) + 5 )
It is evaluating y = 3 first then evaluating ( z = ++y + 2 )
My Problem :
It should first evaluate ( z = ++y + 2 ) because the precedence of comma(,) is much less than parenthesis
My way of Thinking :
Due to precedence we select outer parenthesis
Then we need to evaluate parenthesis
Under this (parenthesis) I again started applying precedence rule
So I took inner bracket to evaluate first
P.S. :
This is not a Duplicate
I have already gone through these links but still unable to understand
Behavior of comma operator in C
C comma operator
What does the comma operator , do?
https://learn.microsoft.com/en-us/cpp/cpp/comma-operator
Uses of C comma operator
https://en.wikipedia.org/wiki/Comma_operator
You're confusing operator precedence with order of evaluation.
Operator precedence dictates how subexpressions are grouped. It does not dictate when each operand is evaluated.
The comma operator has a sequence point between its left operand and its right operand. In the case of y = 3, ( z = ++y + 2 ) + 5, that means that y = 3 must be fully evaluated before ( z = ++y + 2 ) + 5 can be evaluated.
Note also in the subexpression ( z = ++y + 2 ) + 5 that there is no guarantee that everything inside the parenthesis are evaluated before everything inside. You only know that ( z = ++y + 2 ) and 5 are evaluated before ( z = ++y + 2 ) + 5 is evaluated. If for example you had (z = ++y + 2) + y this would invoke undefined behavior because the second y could be evaluated before or after the side effect of ++y.
As another example, if you had x = (func1() + 3) + func2(), either func1 could be called first or func2 could be called first since the order of evaluation of operands is unspecified. If both of those functions modified the same global variable, you wouldn't be able to reliably know the value of that variable.
Precedence and evaluation order are different things. In the expression (a*b) - (c+d), the compiler is free to evaluate (c+d) before (a*b), even though multiplication has higher precedence than addition. But in the expression a,b, as well as the code a;b, the compiler is required to sequence the computation of a before the computation of b.
You are confused between Precedence and Order of Evaluation. Precedence is the priority for grouping different types of operators with their operands.
The comma (,) operator constitute Sequence Point and therefore guarantee a particular order of evaluation for their operands which is left to right.
Order of evaluation
Ordering
......
If a sequence point is present between the subexpressions E1 and E2, then both value computation and side effects of E1 are sequenced-before every value computation and side effect of E2
Rules
.....
2) There is a sequence point after evaluation of the first (left) operand and before evaluation of the second (right) operand of the following binary operators: && (logical AND), || (logical OR), and , (comma).
In this expression:
x = ( y = 3, ( z = ++y + 2 ) + 5 )
First y = 3 will be evaluated first and then ( z = ++y + 2 ) + 5.
I was asking myself if its was possible to do something like that :
condition ? do this && THIS : else;
like :
nb = (nb1 + nb2) > 9 ? (nb1 + nb2) % 10 && nb1 + 1 : 0;
Note this is just an example, it means nothing.
There is a simple way:
condition ? function_that_does_several_things() : else_expr;
The other thing is you can collect expressions in a list:
int a = (1,2);
assigns 2 to a. So you can try this:
condition ? (do_this, and_this) : else_expr;
But I suggest against it; it's really hard to see what is going on here and a lot of people will be confused, surprise and frustrated when they see such code.
It's not "do this", it's "evaluate this". Remove the condition and the "false" path, and you get this:
nb = (nb1 + nb2) % 10 && nb1 + 1;
So, yes, you can do it, but the value of nb will be the result of a logical expression ... which is essentially this:
nb = ((nb1 + nb2) % 10 != 0) && (nb1 + 1 != 0);
This is the DFA i have drawn-
Is it correct?
I am confused because q4 state has 2 different transitions for same input symbol which violates the rule of DFA, but I can't think of any other solution.
Your DFA is not correct.
your DFA is completely wrong so I don't comment
DFA for RE:
0(1 + 0)*0 + 1(1 + 0)*1
Language Description: if string start with 0 it should end with 0 or if string start with 1 it should end with 1. hence two final states (state-5, state-4).
state-4 : accepts 1(1 + 0)*1
state-5 : accepts 0(1 + 0)*0
state-1 : start state.
DFA:
EDIT :
+ Operator in Regular Expression
(0 + 1)* = (1 + 0)* that is any string consist of 1s and 0s, including Null string ^.
Here + means Union if it appear between two RE: and A U B = B U A (similarly)=> (0 + 1) = (0 + 1) .
meaning of plus + depends on syntax it appears in: If expression is a+ (+ is superscripted) this means one of more as, and If a+b then + means Union operation either a or b.
a+ : { a, aa, aaa, aaa.....} that is any number of a string in language with length > 1.
I think you should start with 0 first
0(1 + 0)*0 + 1(1 + 0)*1