tags:

views:

149

answers:

5

This part of my code works fine:

#include <stdio.h>

int main(){
    //char somestring[3] = "abc";
    int i, j; 
    int count = 5;

    for((i=0) && (j=0); count > 0; i++ && j++){
        printf("i = %d  and j = %d\n", i, j);
        count--;
    }

    return 0;
}

The output as expected:

i : 0 and j : 0
i : 1 and j : 1
i : 2 and j : 2
i : 3 and j : 3
i : 4 and j : 4

Things get weird when I uncomment the char string declaration on the first line of the function body.

#include <stdio.h>

int main(){
    char somestring[3] = "abc";
    ...
}

The output:

i : 0 and j : 4195392
i : 1 and j : 4195393
i : 2 and j : 4195394
i : 3 and j : 4195395
i : 4 and j : 4195396

What's the logic behind this? I'm using gcc 4.4.1 on Ubuntu 9.10.

+17  A: 

j never gets initialised, because of the short-circuiting behaviour of &&. Since (i=0) evaluates to false, (j=0) never gets executed, and hence j gets a random value. In the first example, that just happens to be zero.

You should say i=0, j=0 to achieve what you want.

The i++ && j++ has the same problem; it should be i++, j++.

Also, this:

char somestring[3] = "abc";

is reserving one too few bytes, because of the trailing NUL character in the string - you need four bytes. But if you're not going to modify the string, you don't need to specify the number of bytes - you can simply say this:

char *somestring = "abc";

instead.

RichieHindle
The last line would be better written as '`char somestring[] = "abc";`' in that it is still an array and modifiable whereas you've transformed `somestring` into a pointer to a non-modifiable area. It does depend on how the variable is used. In the initialization phase, you could write '`i = j = 0`'. Good answer otherwise.
Jonathan Leffler
Your `somestring` is a pointer while the original `somestring` (mike's) was an array. A better solution that wouldn't break existing code was to define `char somestring[] = "abc";`, so that `sizeof` would still return a meaningful value etc..
conio
@Jonathan, @conio: Good point, but I think it's unlikely that Mike was going to rely on the string being writeable. I would err on the side of putting strings into write-only memory until I knew I needed to write to them. Answer amended anyway.
RichieHindle
+1  A: 

for((i=0) && (j=0)... seems to be incorrect already.
i=0 has already value of 0, so the evaluation of j=0 is not needed, so it is skipped.

(i++) && (j++) seems to be incorrect for the very first iteration, too, by the same reason.

Vlad
+2  A: 

If you use &&, only the first argument gets evaluated if it's false. i=0 is false, so j doesn't get set to 0. You should use the komma operator:

for((i=0) , (j=0); count > 0; i++, j++){ [...]
Juri Robl
A: 

You are using (i==0) && (j==0) to initialise both variables in your loop.

However, a property of && is that if the first operand evaluates to FALSE (i.e. 0), the second operand is never executed. So, as i is 0, j is left uninitialised. In your first run, you were simply lucky that it happened to contain the value 0.

Jason Williams
A: 

Your variables i & j aren't initialized. What do do mean by (i=0) && (j=0)? The compiler will make a shortcut and only assign i=0 j remains uninitialized with the effect you described.

stacker