Can it be assumed a evaluation order of the function parameters when calling it in C ?
No, it can not be assumed if, it is unspecified behavior, the draft C99 standard in section6.5
paragraph 3
says:
The grouping of operators and operands is indicated by the syntax.74) Except as specified
later (for the function-call (), &&, ||, ?:, and comma operators), the order of evaluation of subexpressions and the order in which side effects take place are both unspecified.
It also says except as specified later and specifically sites function-call ()
, so we see that later on the draft standard in section 6.5.2.2
Function calls paragraph 10
says:
The order of evaluation of the function designator, the actual arguments, and
subexpressions within the actual arguments is unspecified, but there is a sequence point
before the actual call.
This program also exhibits undefined behavior since you are modifying pa
more than once between sequence points. From draft standard section 6.5
paragraph 2
:
Between the previous and next sequence point an object shall have its stored value
modified at most once by the evaluation of an expression. Furthermore, the prior value
shall be read only to determine the value to be stored.
it cites the following code examples as being undefined:
i = ++i + 1;
a[i++] = i;
Important to note that although the comma operator does introduce sequence points, the comma used in function calls is a separator and not the comma operator
. If we look at section 6.5.17
Comma operator paragraph 2
says:
The left operand of a comma operator is evaluated as a void expression; there is a
sequence point after its evaluation.
but paragraph 3
says:
EXAMPLE As indicated by the syntax, the comma operator (as described in this subclause) cannot appear in contexts where a comma is used to separate items in a list (such as arguments to functions or lists of initializers).
Without knowing this, having warnings turned on with gcc
using at least -Wall
would have provided a message similar to:
warning: operation on 'pa' may be undefined [-Wsequence-point]
printf("a[0] = %d\ta[1] = %d\ta[2] = %d\n",*(pa), *(pa++),*(++pa));
^
and by default clang
will warn with a message similar to:
warning: unsequenced modification and access to 'pa' [-Wunsequenced]
printf("a[0] = %d\ta[1] = %d\ta[2] = %d\n",*(pa), *(pa++),*(++pa));
~ ^
In general it is important to understand how to use your tools in the most effective way, getting to know the flags available for warnings is important, for gcc
you can find that information here. Some flags that are useful and will save you a lot of trouble in the long run and are common to both gcc
and clang
are -Wextra -Wconversion -pedantic
. For clang
understanding -fsanitize can be very helpful. For example -fsanitize=undefined
will catch many instances of undefined behavior at runtime.