No, some sequences are undefined. The comma operator(a) is not one of those.
Appendix C of ISO C17
(latest iteration at the time of this question) lists the sequence points in C. These sequence points are defined such that all operations and side effects before the sequence point have (or act as if they have) completed fully before any of those after it begin.
One of those sequence points is given as:
Between the evaluations of the first and second operands of the following operators: logical AND &&
(6.5.13); logical OR ||
(6.5.14); comma ,
(6.5.17)
You should also note that, due to precedence rules (=
is higher than ,
), the expression errno = ENOSYS, -1
is effectively [errno = ENOSYS], [-1]
rather than errno = [ENOSYS, -1]
, using []
to indicate the sub-expressions.
That means the sub-expression setting errno
is done (with that sub-expression evaluating to ENOSYS
(b)), then the complete expression ENOSYS, -1
, has a result of -1
.
It's the same as the difference between x = 1, 2
and x = (1, 2)
. The former sets x
to one and the full expression gives two. The latter sets x
to two because the result of 1, 2
is two and the parentheses have higher precedence than assignment.
(a) This is distinct from the comma when not used as an operator, such as when used to separate parameters to a function.
(b) This is what allows things like a = b = 42
. Assignment has right-to-left associativity so it's effectively a = (b = 42)
.
So b
is set to forty-two and the result of that assignment is that value, which is then assigned to a
.