Toothpick Anemone
Toothpick Anemone

Reputation: 4636

How are complicated expression using the comma operator parsed in C?

After reading both of the following...

What does the comma operator , do?

How does the Comma Operator work

I am still not sure that I can't parse the following statement that I found in someone else's source code:

int i, n, val, locala = a, bestval = -INFINITY;

The comma operator is evaluated in left-to-right ordering, yes? If we use parentheses to show order of precedence, I think we have something like this:

(int i, (n, (val, (locala = a, (bestval = -INFINITY)))));

So, maybe, the original is equivalent to the following?

int bestval = -INFINITY;
int locala = a;
int val;
int n;
int i;

If so, why is the int keyword applied to all of the variables instead of only the leftmost variable i?

Also, the right-most expressions return their value, yes? So, locala = a might return the value of locala after the assignment is takes place. Does that mean that the variables i, n, and val all get initialized? If so, what do they get initialized to? -INFINITY? the value of a?

Upvotes: 1

Views: 87

Answers (3)

aschepler
aschepler

Reputation: 72431

The comma token does several different things in C, which should not be confused:

  • Separates the parameters of a function-like preprocessor macro definition:

    #define CAT_NO_EXPAND(x,y) x ## y
    
  • Separates the arguments of a function-like preprocessor macro use:

    int CAT_NO_EXPAND(ident_, 3) = 3;
    
  • Separates the enumerators in an enum definition:

    enum colors { RED, GREEN, BLUE };
    
  • Separates the declarators in a declaration:

    int a, b=3, c;
    
  • Separates the members/elements in a braced initializer:

    int arr[3] = {0, 2, 4};
    struct mystruct s = {8, 3.0};
    func( (mystruct s){8, 3.0} );
    
  • Separates the parameters of a function declaration or definition:

    void f(int n, double, const char* fmt, ...);
    
  • Separates the arguments of a function call expression:

    f(3, 0.5, "Test %s\n", "Hello");
    
  • Forms an expression which if evaluated will discard the left side and use the value of the right side as its value.

    #define CALL_G_IGNORE_RESULT(x) ((void)g(x), 0)
    for (i=0, j=0; i<m && j<n; ++i, ++j)
    

What you have read about the "comma operator" is only describing the last case, which works in an expression context that doesn't match any of the other cases above.

What you posted is a declaration, which does not involve the "comma operator" and simply declares multiple variables at once. Any initializers are evaluated in order (which matters because you can use an earlier-declared variable in a later initializer).

Upvotes: 3

user207421
user207421

Reputation: 311018

  1. This is not the comma operator.
  2. It is a declaration list.
  3. It is executed left to right, or at least the executable parts of it are.
  4. Evaluation order and operator precedence are two different things.
  5. Left-to-right execution order is the opposite of what you posted in parentheses.
  6. The int keyword is applied to all the declarations because that's what the syntax means.
  7. There are no 'right-most expressions' here, only declarations with initializers.
  8. There are therefore no values returned either.
  9. i, n, and val are not initialised.

Upvotes: 0

Vlad from Moscow
Vlad from Moscow

Reputation: 311088

This

int i, n, val, locala = a, bestval = -INFINITY;

is a declaration.

The declaration is defined the following way in C (without all details)

declaration:
    declaration-specifiers init-declarator-listopt ;

init-declarator-list:
    init-declarator
    init-declarator-list , init-declarator

init-declarator:
    declarator
    declarator = initializer

The declaration-specifiers affects all declarators in the init-declarator- list.

If you want to use the comma operator in a declaration then such a declaration can look for example like

int i = 1, j = 2, k = ( ++i, j++, i + j );

Here the expression ( ++i, j++, i + j ) used as an initializer based on the comma operator.

After the declaration i is equal to 2, j - 3, and k - 5.

Upvotes: 4

Related Questions