I presume your question is about which increments will actually occur.
&& and || (logical and and logical or) are "short-circuit" operations. They evaluate only enough of their arguments to determine whether they're true or false. Effectively, x && y can be treated as x ? y : 0 and x || y can be treated as x ? 1 : y
&& takes precedence over ||, so start by looking at i++ && j++ && k++. This starts by evaluating i++, returning -1 and setting i to 0. Since the returned value is true (nonzero), we continue by evaluating j++, which once again returns -1 (true) and increments j to 0. We still haven't proven the value of the &&, so we evaluate k++, which returns 0 (false) and increments k to 1. That false gives us a final anded value of false.
Now we proceed to the ||. Effectively, you now have false || l++. The false is not enough to determine the result of the or, so we evaluate l++. That returns 2 (true), while setting l to 3. That true forces the value of the ||, and the final value of the expression, to be true.
Note that if i, j, or k had started as 0 (false), the later increments would not have occurred, since short-circuit evaluation would have decided they weren't needed in order to produce a result. In general, mixing && or || with side effects is a bad idea for exactly this reason -- it produces logic that is needlessly hard to understand. The ?: versions -- or a real if/then/else statement -- would make this interaction much, much clearer. You should understand how to read this sort of mess, because you will run into it in other programmers' C code -- but you should almost never write it. And if you must, you should document it to death. The sanity you save may be your own.