int m= i++ || ++j && k--;

where i=2, j=3, amd k=5;
acooridng to me, it will be executed left to right and then values of m=1, i=3, j=3 and k=5. but i have seen that precednace of && is more than || , than so how this expression is parenthezed by compiler to execute it ?

as it goes to i++, and since it is non-zero , then it dont need to check after this, so stoped there. (this is what i thought before reading that precdance of && is more than || ). so what is wrong here and where ? thanks alot.

Recommended Answers

All 14 Replies

where have you seen that the precedence of && is greater than ||?

It's parenthesized like this:

int m = (i++ || (++j && k--));

But || is still a left to right short circuiting operator, so i++ is evaluated first. If it evaluates to true, (++j && k--) doesn't get evaluated. But if i++ evaluates to false, the right hand side of the OR expression is the final result of the AND expression. In other words:

if (i++)
{
    m = 1;
}
else
{
    m = (++j && k--);
}

sir,
was reading some problems on net, come through this one.

void fun(char**);

int main()
{
      char * argv[]={"ab","cd","ef","gh";
      fun(argv);
      return 0;
}

void fun(char **p)
{
       char *t;
       t+=(p+=sizeof(int))[-1];      // line xyz
       printf("%s\n",t);
}

// assume sizeof int is 4 bytes here

Can you explain me this ? I am not able to grab it completely . specially throw some light on line xyz as i have marked this in code snippet. thanks.

First note that foo += bar is an expression that increments foo by bar and then evaluates to foo. So t += (p += sizeof(int))[-1]; can be rewritten as:

p += sizeof(int);
t += p[-1];

that should be a little clearer already. Next note that foo[bar] is simply a syntactic shortcut for *(foo + bar), i.e. it adds an offset to a pointer and then dereferences it. So p[-1] accesses the value that's at the address one before the address that p points to now.

Since the value of p is never used again in this function, the fact that p was incremented doesn't really matter. So the clearest way to rewrite the function would be:

void fun(char **p)
{
    char *t;
    t += p[ sizeof(int) - 1 ]; // line xyz
    printf("%s\n",t);
}

Note that, since t is never initialized, the whole thing invokes undefined behavior. I think that the += is an error and what was intended might be:

void fun(char **p)
{
    char *t;
    t = p[ sizeof(int) - 1 ]; // line xyz
    printf("%s\n",t);
}

but i am pointing p to a location which is out of array bound firstly. then i am decreasing value from it to point it to previous location. is it correct ?

secondly, is it correct if i do this.

void fun(char **p)
{
       char *t;
       t=(p+=(sizeof(int)+2)))[-3];      // line xyz
       printf("%s\n",t);
}

will it still work ? i dont know , but will it always be correct to go out of range of array first then take it value by decreasing the subscript ? thanks.

According to the standard, you may have a pointer that points one past the last element of an array, but no further. So if you have an array of size n and p points to that array, you may do p+n (though you may not dereference it), but doing p + n + 1 will invoke undefined behavior. So, assuming that sizeof(int) is 4, (p += sizeof(int))[-1] would be okay, but (p += sizeof(int) + 2)[-3] would invoke undefined behavior (since p points to an array of four elements in your example).

That said, I'm not aware of any implementation where having a pointer that points past the end of an array will produce anything but the expected outcome (assuming, of course, you don't dereference the pointer).

wonderful explaination! and what about the case if i take one step back of the first element of the array , then ? and secondly, if i take my pointer 3 step back from the first element of array and then taking it back to the 1st or 2nd element ? is there anything defined for this case in standard ? thanks alot.

@deceptikon , then in my example, what's the difference between order of precedence and order of evaluation ? if && has higher precedence but still || component is evaluated first ? please can you make it clear to me ? thanks to you.

one step back of the first element of the array

I think that's undefined. As far as I know, the only exception is one past the end of the array. In any other case, any pointer arithmetic invokes undefined behavior if the resulting pointer does not point inside the object that the original pointer pointed into.

3 step back from the first element of array and then taking it back to the 1st or 2nd element

Definitely undefined.

then in my example, what's the difference between order of precedence and order of evaluation ?

If || had higher precedence than &&, we'd get int m = ((i++ || ++j) && k--);. This behaves differently from int m = (i++ || (++j && k--)) in the following way:

In the first case k-- gets evaluated if i++ is true or if ++j is true. In the second case, k++ only gets evaluated if i++ is false and j++ is true. This also means that in the first case it is possible for k-- to be evaluated when ++j was not evaluated, but in the second case k-- can only be evaluated if both i++ and ++j have been evaluated.

So you see: the meaning (and thus the result) of the expression changes with different precedence rules, but the order in which the operations happen stays the same. That is i++ will always happen before ++j (assuming ++j happens at all) and ++j will always happen before k-- (assuming both ++j and k-- happen), but the way in which they depend on each other changes.

commented: awesome !! +2

if i want to differ between the order of precedence and order of evaluation, then i can say that oder of evaluation is always same, but order of precedence help us to paranthize the expression ? still, i am not very clear about this difference.

Secondly, that mean order of precedence doesn't mean that the brackets that are put by compiler will be excecuted before everything ? order of evaluation is not effected by order of precedence ? your explainations are really appreciable. thanks if you can help me.

Consider this:

int f() {
    puts("F was called\n");
    return 0;
}

int g() {
    puts("G was called\n");
    return 0;
}

int h() {
    puts("H was called\n");
    return 1;
}

int main() {
    int res1 = (f() && g()) || h();
    int res2 = f() && (g() || h());
    return 0;
}

The order in which the functions are called will be: f, h for res1 and just f for res2. The results will be res1 = 1 and res2 = 0. There is no way to parenthesize the expressions, so that "G was called" or "H was called" would be printed before "F was called".

yeah.. i am getting this thing which you have tried to explain me in this example. but can you please read by last post and answer the question which i have asked word to word ? actually, i was confused a lot in this. you have made it very clear, still some doubt is left.

again, predenece of operators just help us to parenthesize the expression ? can you please take an example by having some different operators in it which have varied predence, including those having same predence and have some associativity thing in this (right to left , left to right)?

what is the thing when we say internal bracket is solved firstly ? but as in ur example this thing is not there. please make me correct as it is going dangerious for me. thanks a lot.

There are 2 things describing how/what order operators in an expression are evaluated; preceddence and associativity.

It is important to remeber that associativity is only ever applied to a series of operators of the same preceedence, that is in the line a = b + c; the associativity of the 2 operators, right-to-left for = and left-to-right for + do not come into play at all because = and + have different precences.

Preceedence only affects how the operands bind to the operators not the order in which the operators are evaluated; in A || B && C preceedence indicates that B and C will bind to && but the || operator is evaluated first.

Associativity defines the order in which operators are evaluated (and therefore sometimes how the operands bind to them) in a + b + c + has left-to-right associativity and therefore the left hand + is evauluated first and b binds to the first plus so it is equivilent to (a + b) + c.

A couple of operators, notably && and || have special rules (shortcut evauluation) which have to be taken into account when the order of evaulation is determined.

However that asside I believe there is no constraint on the compiler to evaulate in a specific order as long as it has satisfied the rules of precedence and associativty and the operators used; i.e. in a * b + c * d * has higher preceedence than + so this is evaulated as (a * b) + (c * d) however the compiler is not constrained to evaluate a * b and c * d in any particular order except that it must have evaluated them both before evaluating the +.

All of this needs to be taken into account when determining the evaluation of an expression so in

a = b += *p++ + c * d / ++e << f;

Knowing the preceedence is the starting point in order operators on the same preceedence on the same line

++(postfix)
*(indirection) ++(prefix)
*(multiplication) /
+
<<
= +=

If we add the parenthese for preceedence we get

a = b += (((*(p++)) + (c * d / (++e))) << f);

At the top level we have = and += which have the same preceedence and are right-to-left associative so += gets evaluated first and internally we have a * and / which have the same preceedence and are left-to-right so the * gets evaluated first add that in and you get.

a = (b += (((*(p++)) + ((c * d) / (++e))) << f));

At this point the expression is unambiguous it does not matter the actual order you evaluate any operator excepting that you must have the values of all of its operands before you do; i.e. if you decide to evalutate / first you must perforce evaluate the (c * d) and (++e) first because you need the values of those as the operands of the / operator.

commented: incredible post!! +2

@banfa firstly, example you have given is of many millions! made me clear of many many doubts.

one thing, you said that order of evaluation doesnt matter. but till the time last expression is not in our hand, till that time order of evalution will matter ? for ex: c*d / , in his case you have parethsized the expression. this mean that it is important to do so otherwise we may get wrong results ? right ?

until we dont have unambigious parenthisezied expression, we take order of evaluation ? I mean oder of evaluation comes into picture when it is done with the parenthazation ? am i right ? and we must take care in case of only 2 operators (&& , ||) right ? make me correct .thanks.

When I say order of evaluation is unimportant I mean that order of evaluation is not important once you have resolved all the preceedence and associativity rules if they are then multiple things you could do first.

So in a * b + c * d were you could evaluate a * b first or c * d first it is not important which of these 2 sub-expressions are evaluated first and the compiler is free to choose. Then once it has evaluated both sub-expressions it can evaluate the +.

However in an expression like a + b * c once you have resolved the preceedence then it is clear that b * c must be evaluated before the +.

So yes as you say order of evaluation only comes into the picture once all the parenthases have been (conceptually) assigned. Once that is done it is order of evaluation is either self-evident as in a + b * c or it does matter as in a * b + c * d or in the case of || and && there are further rules that have to be followed, that is left hand expression is always evaluated before the right hand expression and the right hand expression is then not evaluated if the value of the left hand expression gives the result of the operator.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.