8
while(*p!='\0' && *q!='\0')
{
        if(*p==*q)
        {
               p++;
               q++;
               c++;
        }
        else
        break;
}

I have written this using ternary operator but why its giving error for break statement?

*p==*q?p++,q++,c++:break;

gcc compiler gives this error: expected expression before ‘break’

Arc676
  • 4,445
  • 3
  • 28
  • 44
Shubham S. Naik
  • 341
  • 1
  • 4
  • 14
  • 18
    Because `break;` is an statement, not expression. – MikeCAT Jun 16 '16 at 09:37
  • 1
    While pointer arithmetic in often nice, and is one of the features of C that few other languages have, it's not *always* the best solution. If you reorganize your loop to use a `size_t i` as the iterator, the code gets much better, without losing performance on any reasonable architecture. – EOF Jun 16 '16 at 09:41
  • 1
    Possible duplicate of [Why can't I use a "break" statement inside a ternary conditional statement in C++?](http://stackoverflow.com/questions/28642693/why-cant-i-use-a-break-statement-inside-a-ternary-conditional-statement-in-c) – Twahanz Jun 16 '16 at 09:45
  • 1
    The `?:` ternary operator produces a value, and all three of its operands are expressions. `break` is a statement, not an expression. It does not produce a value. You might as well ask "Why can't I add `5` to `break`?", or "Why can't I pass `break` as a function argument?" Answer: Because `break` isn't an expression. – Tom Karzes Jun 16 '16 at 09:48
  • 1
    Even if it workd, do you really think `*p==*q?p++,q++,c++:break;` is more readable? – Jabberwocky Jun 16 '16 at 09:53
  • 1
    Consider replacing this whole messy code with `while(*p == *q && *p != '\0) { p++; q++; c++; }`. – Lundin Jun 16 '16 at 10:02
  • 1
    @Lundin That is not *quite* semantically equivalent. If `q` is not null-terminated, you could be indexing out-of-bounds where the OP's code isn't. – EOF Jun 16 '16 at 10:17
  • 2
    @EOF The semantics are the same as in OP's code. If either `p` or `q` is null-terminated, the while condition is evaluates to `false`. If both are null, second condition terminates the loop. If one is null and the other isn't, the first condition terminates the loop. Neither solutions is safe if neither `p` nor `q` is null terminated and happen to go out of bounds in a way that produces equal values being read. But the only error is the missing `'` in `'\0'`. – sendaran Jun 16 '16 at 10:38
  • @EOF If either of the strings is not null terminated, nothing of this makes any sense and the code will crash and burn. – Lundin Jun 16 '16 at 11:12
  • @Lundin If `p` is null-terminated and `q` is not, but both are equal until `p`'s null-terminator, your code accesses `q` out of bounds, while the OP's code doesn't, because `*p && ...` does not access the `&& ...` part if `*p` evaluated to `0`. – EOF Jun 16 '16 at 11:43
  • @sendaran: You are incorrect. `while (*p && *q)` doesn't access `*q` if `*p` evaluates to `0`. Learn about short-circuit evaluation. – EOF Jun 16 '16 at 11:47
  • @EOF if *p was zero, *q must have been zero too, otherwise the `*p == *q` would've evaluated to false. – Tommylee2k Jun 16 '16 at 11:50
  • @Tommylee2k: But the damage is *already done*, because you have accessed `*q` when you shouldn't have. – EOF Jun 16 '16 at 11:50
  • @EOF only if the terminating zero is not part of *q ... and the OP doesn't check this either – Tommylee2k Jun 16 '16 at 11:52
  • @Tommylee2k: I'll make this simple, so maybe all of the people arguing against me will understand: Imagine `p` is an empty string from the beginning: `*p == 0` when the loop-condition is first checked. In that case `q` can be `NULL` in the OP's code without crashing or undefined behavior. In @Lundin's variant, it *cannot*. **Not semantically equivalent**. – EOF Jun 16 '16 at 11:54
  • @EOF gotcha. even if that's nullpointer access, not running out of bounds :) so he'd better used `while (*q && *p && *q++==*p++) c++;' – Tommylee2k Jun 16 '16 at 12:06
  • @Tommylee2k: I tried to find a simple example that is immediately obvious. The same problem occurs if `q` is not null-terminated and `p` *is*, and both strings are the same until `p`'s null-termination, and `q` ends there. BTW, your code must be `while (*p && ...)` rather than `while(*q && ...)`, otherwise you've changed *which* of `p` and `q` can be unterminated – EOF Jun 16 '16 at 12:29
  • @EOF OP's code accesses the pointers in a similar way in the while condition `while(*p!='\0' && *q!='\0')`. Also, you first mentioned null-termination only and now you are arguing about null pointers, which is another story completely. You are making yourself a moving target. SO does not like moving targets. "Learn about short-circuit evaluation" is uncalled for, my comment already relies on it. If `p` or `q` is a null pointer, OP code crashes as well, exception being the corner case of empty string `p` and null pointer `q`. I'll admit omitting "If both are null-*terminated*", out of chars. – sendaran Jun 16 '16 at 12:29
  • @sendaran: "[the] exception being[...]"? **Not. Semantically. Equivalent.** I'm not moving the goalposts, I'm giving an example even *you* can understand. – EOF Jun 16 '16 at 12:31
  • @EOF lol yea sure, `*p && *q` ... looks like now i'm REALLY getting confused – Tommylee2k Jun 16 '16 at 14:22

2 Answers2

8

When you use a ternary operator, it is not like an if. The ternary operator has this form:

(condition ? expression_if_true : expression_if_false);

Those two expression must have the same type, otherwise that makes nonsense.

And as Thilo said, you cannot use statement in this operator, only expression. This is because the whole ternary operator must be an expression itself, depending on the condition.

Boiethios
  • 38,438
  • 19
  • 134
  • 183
6

The syntax is:

(condition ? expr_true : expr_false);

expr_true and expr_false must have a common type (which will be the result of the ternary operator). Also, of course, break is not an expression, it is a statement.

Mattia F.
  • 1,720
  • 11
  • 21