1

I'm observing different behavior regarding what I think is part of the C standard between clang and gcc (either the homebrew version on my mac or on linux). The question is whether the comma in an argument list is a sequence point or not. clang interprets it as such but gcc does not.

This code demonstrates the issue:

#include <stdio.h>

int inner(int *v) {
  *v += 1;
  return 1;
}

int outer(int x, int y) {
  return y;
}

int main(int argc, char *argv[]) {
  int x = 4;
  printf ("result=%d\n", outer(inner(&x), x));
}

And the results:

$ clang -o comseq comseq.c && ./comseq
result=5
$ gcc-4.8 -o comseq comseq.c && ./comseq
result=4
$ gcc-5 -o comseq comseq.c && ./comseq
result=4

I don't have access to a copy of the C standard at the moment, but I was pretty sure that clang's behavior was correct until I saw gcc's interpretation. Playing with the --std= option didn't change my results at all.

ETA

On a better reading it is true that this question is answered in https://stackoverflow.com/a/4176333/3171657:

a , b (§5.18) (in func(a,a++) , is not a comma operator, it's merely a separator between the arguments a and a++. The behaviour is undefined in that case if a is considered to be a primitive type)

but that, while very useful, is a long answer so maybe leaving this question around will help other users like myself. Also, to be pedantic, that question is about C++, not C.

Community
  • 1
  • 1
Turn
  • 6,656
  • 32
  • 41
  • 8
    Commas in argument lists are not sequence points — they are not comma operators within the meaning of the term. – Jonathan Leffler Dec 27 '15 at 01:39
  • 4
    The *comma operator* is a sequence point... but not all commas are comma operators. – Dmitri Dec 27 '15 at 01:42
  • 1
    I guess `clang` didn't treat the commas as sequence points but it *happened* to evaluate the arguments from left to right. `clang` generated [warning for unseqnenced modification](http://melpon.org/wandbox/permlink/gEObnyAHNanRT8bo) when I used `+=` operator directly in the argument. – MikeCAT Dec 27 '15 at 01:45
  • 1
    Possible duplicate of [Undefined behavior and sequence points](http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points) – phuclv Dec 27 '15 at 01:56
  • Example does not prove "clang interprets it as such". – chux - Reinstate Monica Dec 27 '15 at 02:24

2 Answers2

5

Commas in argument lists are not sequence points — they are not comma operators within the meaning of the term.

The section of the standard (ISO/IEC 9899:2011) on function calls (§6.5.2.2) says:

¶3 A postfix expression followed by parentheses () containing a possibly empty, comma- separated list of expressions is a function call. The postfix expression denotes the called function. The list of expressions specifies the arguments to the function.

¶4 An argument may be an expression of any complete object type. In preparing for the call to a function, the arguments are evaluated, and each parameter is assigned the value of the corresponding argument.

¶10 There is a sequence point after the evaluations of the function designator and the actual arguments but before the actual call. Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function.

(I've omitted a couple of footnotes, but the contents are not germane to the discussion.)

There is nothing about the expressions being evaluated in any particular sequence.

Note, too, that a comma operator yields a single value. If you interpreted:

function(x, y)

as having a comma operator, the function would have only one argument — the value of y. This isn't the way functions work, of course. If you want a comma operator there, you have to use extra parentheses:

function((x, y))

Now function() is called with a single value, which it the value of y, but that is evaluated after x is evaluated. Such notation is seldom used, not least because it is likely to confuse people.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
4

The order of evaluation of function arguments is unspecified, so comma used as separator of arguments won't be sequence points.

N1256 6.5.2.2 Function calls

10 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.

If you use comma operator in arguments, it will be a sequence point.

#include <stdio.h>

int inner(int *v) {
  *v += 1;
  return 1;
}

int main(int argc, char *argv[]) {
  int x = 4;
  printf ("result=%d\n", (inner(&x), x));
}
MikeCAT
  • 73,922
  • 11
  • 45
  • 70