tags:

views:

2350

answers:

6

I would like to increment 2 variables in a for-loop condition instead of one.

So something like:

for(int i = 0, i != 5; ++i and ++j) do_something(i,j);

What is the syntax for this?

+24  A: 

Try this

for(int i = 0; i != 5; ++i, ++j)
    do_something(i,j);
yeyeyerman
+1 You can also declare j in the first part. for(int i = 0, j = 0; i != 5; ++i, ++j) { ... }
Daniel Daranas
+3  A: 

for(int i = 0, i != 5; ++i, ++j) do_something(i,j);

malay
A: 
int main(){
    int i=0;
    int a=0;
    for(i;i<5;i++,a++){
        printf("%d %d\n",a,i);
    } 
}
Arkaitz Jimenez
What's the point of not making `i` and `a` local to the loop?
sbi
None, just showing how to do both increments in the for, its just an example of the sytnax
Arkaitz Jimenez
+18  A: 

A common idiom is to use the comma operator which evaluates both operands, and returns the second operand. Thus:

for(int i = 0; i != 5; ++i,++j) 
    do_something(i,j);

But is it really a comma operator?

Now having wrote that, a commenter suggested it was actually some special syntactic sugar in the for statement, and not a comma operator at all. I checked that in GCC as follows:

int i=0;
int a=5;
int x=0;

for(i; i<5; x=i++,a++){
    printf("i=%d a=%d x=%d\n",i,a,x);
}

I was expecting x to pick up the original value of a, so it should have displayed 5,6,7.. for x. What I got was this

i=0 a=5 x=0
i=1 a=6 x=0
i=2 a=7 x=1
i=3 a=8 x=2
i=4 a=9 x=3

However, if I bracketed the expression to force the parser into really seeing a comma operator, I get this

int main(){
    int i=0;
    int a=5;
    int x=0;

    for(i=0; i<5; x=(i++,a++)){
        printf("i=%d a=%d x=%d\n",i,a,x);
    }
}

i=0 a=5 x=0
i=1 a=6 x=5
i=2 a=7 x=6
i=3 a=8 x=7
i=4 a=9 x=8

Initially I thought that this showed it wasn't behaving as a comma operator at all, but as it turns out, this is simply a precedence issue - the comma operator has the lowest possible precedence, so the expression x=i++,a++ is effectively parsed as (x=i++),a++

Thanks for all the comments, it was an interesting learning experience, and I've been using C for many years!

Paul Dixon
I've read several times that the comma in the first or third part of a for loop is *not* the comma operator, but just a comma separator. (However, I fail to find an official source for this, since I'm particularly bad at parsing the C++ language standard.)
Daniel Daranas
I first thought you were incorrect, but I wrote some test code and you are correct - it does not behave like a comma operator. Will amend my answer!
Paul Dixon
+1 for your ammendment. It's a bit counter intuitive to me but most of the times when a comma appears, it's not a comma operator, and this is one of them.
Daniel Daranas
It *is* a comma operator in that context. The reason you aren't getting what you expect is that the command operator has lower precedence than the assignment operator, so without the parantheses it parses as (x = i++), j++.
caf
It IS a comma operator. The assignation ties more strongly than the comma operator, so x=i++,a++ is parsed (x=i++),a++ and not x=(i++, a++). That characteristic is misused by some libraries so that v = 1,2,3; does the intuitive things, but only because v = 1 returns a proxy object for which the overloaded comma operator does an append.
AProgrammer
And now I'm back where I started. Which is good, as I've thought it was comma operator for 20 years!
Paul Dixon
I totally fail to find an explanation in the standard. Some google results say it is a comma operator, some say it isn't. Your example doesn't prove that it actually *is* a comma operator, only that it can be. I remember being told that it wasn't some years ago at the borland.cpp.language newsgroup, but I can't search it anymore. Maybe this could be my first question on Stack Overflow, since every time I think of a question, it already exists, and this does not seem to be the case.
Daniel Daranas
Ok. From http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2857.pdf section 6.5.3 the last part is an "expression". (Although 1.6 #2 defines an "expression-list" as a "list of expressions separated by commas", this construct does not appear in 6.5.3.). This means that when we write "++i,++j" it has to be an expression in an by itself, and thus "," *must be the comma operator* (5.18). (This is not a "list of initializers" or "list of arguments to functions", which are examples where "comma is given a special meaning", as 5.18 #2 says.). I find it a bit confusing though.
Daniel Daranas
+2  A: 

Try not to do it!

From http://www.research.att.com/~bs/JSF-AV-rules.pdf:

AV Rule 199
The increment expression in a for loop will perform no action other than to change a single loop parameter to the next value for the loop.

Rationale: Readability.

squelart
+1  A: 

I agree with squelart, incrementing two variable is bug prone, espcially if you only test for one of them.

for(int i = 0; i < 5; ++i) {
     ++j;
     do_something(i,j);
}

Is the readable way to do this. For loops are meant for cases where your loop runs on one increasing/decreasing variable. Any other variable, change it in the loop.

If you need j to be tied to i, why not leave the original variable as is and add i?

for(int i = 0; i < 5; ++i) {
     do_something(i,a+i);
}

If your logic is more complex (e.g. you need to actually monitor more than one variable), I'd use a while loop.

Neko
In the first example, j is incremented once more than i!What about an iterator where needs to be done some action on for the first x steps? (And the collection is always long enough) You can than ascend the iterator every iteration, but is is much cleaner imho.
Peter Smit