3
void main() {
    int i, j=6;
    for(; i=j ; j-=2 )
        printf("%d",j);
}

By following regular pattern, there should be a condition after first semicolon, but here it is initialization,so this should have given an error. How is this even a valid format?

But the output is 642

Sourav Ghosh
  • 127,934
  • 16
  • 167
  • 234
Nitish Prajapati
  • 129
  • 1
  • 10
  • 2
    It should be an *expression* and assignment is an expression. – Some programmer dude Nov 03 '16 at 06:34
  • 1
    There is no inutialization, there is an assignment. Btw `void main` is non-standard. – n. 'pronouns' m. Nov 03 '16 at 06:36
  • 1
    It's basically shorthand for `(i=j) != 0` since `0` is `false` – 4castle Nov 03 '16 at 06:38
  • Why then the code not print 0,-2,-4.......and so on – Nitish Prajapati Nov 03 '16 at 06:42
  • `void main()` should be `int main(void)`. If a book told you to use `void main()`, find a better book. – Keith Thompson Nov 03 '16 at 06:44
  • 1
    If you compile with clang using `-Wall` you'll get two warnings. The first because you messed up the declaration of `main`. The second because you messed up the `for` statement (used an assignment as a conditional expression). If you aren't compiling with `-Wall` and/or you are ignoring warnings, then I can't adequately express my opinion about that (due to the *"be nice"* policy). – user3386109 Nov 03 '16 at 06:54
  • @user3386109 what actually -Wall stands for – Nitish Prajapati Nov 03 '16 at 06:56
  • 1
    It supposed to stand for *"enable all warnings"*, but in reality it just enables some additional warnings. There's also `-Wextra` and `-Weverything` which will enable even more warnings. – user3386109 Nov 03 '16 at 06:59
  • @user3386109 ok. Got it. Thanks – Nitish Prajapati Nov 03 '16 at 07:00
  • 1
    @Nitish Prajapati: C has no such thing as a dedicated "condition". Every "condition" is basically an arbitrary (non-void) expression that will be implicitly tested for equality to zero. `i=j` is a non-void expression, which means that it can perfectly fine serve as a "condition". – AnT Nov 03 '16 at 07:11
  • [What should main() return in C and C++?](http://stackoverflow.com/q/204476/995714) – phuclv Nov 03 '16 at 07:35
  • @LưuVĩnhPhúc main returns zero(0) always.correct me if I'm wrong. – Nitish Prajapati Nov 03 '16 at 08:37
  • 1
    wrong. if it's always 0 then no need to use the return type int – phuclv Nov 03 '16 at 08:45
  • @NitishPrajapati: You can upvote all answers that help you and accept one of them by clicking on the grey checkmark below its score. – chqrlie Nov 03 '16 at 08:53

4 Answers4

3

i=j is also an expression, the value of which is the value of i after the assignment. So it can serve as a condition.

You'd normally see this type of cleverness used like this:

if ((ptr = some_complex_function()) != NULL)
{
  /* Use ptr */
}

Where some programmers like to fold the assignment and check into one line of code. How good or bad this is for readability is a matter of opinion.

StoryTeller - Unslander Monica
  • 148,497
  • 21
  • 320
  • 399
3

First, let me correct the terminology, the i=j is an assignment, not an initialization.

That said, let's analyze the for loop syntax first.

for ( clause-1 ; expression-2 ; expression-3 ) statement

So, the expression-2 should be an "expression".

Now, coming to the syntax for statement having assignment operator

assignment-expression:
conditional-expression
unary-expression assignment-operator assignment-expression

So, as the spec C11 mentions in chapter §6.5.16, the assignment operation is also an expression which fits perfectly for the expression-2 part in for loop syntax.

Regarding the result,

An assignment expression has the value of the left operand after the assignment,

so, i=j will basically assign the value of j to i and then, the value of i will be used for condition checking, (i.e., non-zero or zero as TRUE or FALSE).

TL;DR Syntactically, there's no issue with the code, so no error is generated by your compiler.


Also, for a hosted environment, void main() should be int main(void) to be conforming to the standard.

Sourav Ghosh
  • 127,934
  • 16
  • 167
  • 234
1

Your code does not contain a syntax error, hence the compiler accepts it and generates code to produce 642.

The condition i=j is interpreted as (i = j) != 0.

To prevent this and many similar error patterns, enable more compiler warnings and make them fatal with:

gcc -Wall -W -Werror

If you use clang, use clang -Weverything -Werror

chqrlie
  • 98,886
  • 10
  • 89
  • 149
1

This is a very good question.

To really understand this, you better know how C codes are executed in computer: First, the compiler will compile the C code into assembly code, then assembly codes will be translated into machine code, which can run in main memory directly.

As for your code:

void main() {
    int i, j=6;
    for(; i=j ; j-=2 )
        printf("%d",j);
}

To figure out why the result is 642, We want to see its assembly code.

Using VS debugging mode, we can see:

enter image description here

Especially look at this:

010217D0  mov         eax,dword ptr [j]  
010217D3  mov         dword ptr [i],eax  
010217D6  cmp         dword ptr [i],0  
010217DA  je          main+4Fh (010217EFh)  

The four lines of assembly code correponding to the C code "i=j", it means, first move the value of j to register eax, then move the value of register eax to i(since computer can not directly move the value of j to i, it just use register eax as a bridge), then compare the value of i with 0, if they are equal, jump to 010217EFh, the loop ends; if not, the loop continues.

So actually it's first an assignment, then a comparision to decide whether the loop is over; as 6 declines to 0 ,the loop finally stops, I hope this can help you understand why the result is 642 :D

Statham
  • 3,374
  • 2
  • 28
  • 43