Bloodknofsky
Bloodknofsky

Reputation: 21

using ";" at the end of for statement but the code still executing

#include <stdio.h>

int main()
{
    int sub[50], i;
    for (i = 0; i <= 48; i++);
    {
        sub[i] = i;
        printf("%d\n", sub[i]);
    }
    return 0;
}

Why is the output is 49?

I think it should not execute the printf function.

Upvotes: 1

Views: 110

Answers (4)

chqrlie
chqrlie

Reputation: 144949

Your program has a classic mistake: the for statement line end with a ;, causing for to have an empty body and the following block to execute unconditionally once with i having the final value at the end of the loop, ie 49.

The for statement ends at the ; and the { on the following line starts a separate block, unrelated to the for statement, that executes unconditionally.

So your program is equivalent to:

#include <stdio.h>

int main()
{
    int sub[50], i;

    for (i = 0; i <= 48; i++); // the compiler will simplify this to i = 49

    sub[i] = i;
    printf("%d\n", sub[i]);

    return 0;
}

I don't know if you added the ; on purpose, but if you did it by mistake, note that the classic K&R style makes this type of mistake much less likely:

#include <stdio.h>

int main() {
    int sub[50], i;
    //for (i = 0; i <= 48; i++); {  // <--- this would immediately catch your eye!
    for (i = 0; i <= 48; i++) {
        sub[i] = i;
        printf("%d\n", sub[i]);
    }
    return 0;
}

Using the c99 new for syntax, you would define i in the for initial clause and the compiler would catch the mistake:

#include <stdio.h>

int main()
{
    int sub[50];
    for (int i = 0; i <= 48; i++);
    {
        sub[i] = i;   //<--- error: `i` is not defined anymore
        printf("%d\n", sub[i]);
    }
    return 0;
}

Creating empty loops purposely with just a trailing ; at the end of the for() line is confusing and error prone. Compilers may flag this with a warning if configured for a higher warning level, which incidentally is very good practice to detect silly mistakes (ie: gcc -Wall -Werror or clang -Weverything -Werror).

If you want an empty body, I would recommend this syntax:

/* find the last node of the list */
if (list) {
    for (cur = list; cur->next; cur = cur->next)
        continue;
    //...
}

Upvotes: 3

anastaciu
anastaciu

Reputation: 23822

for (i = 0; i <= 48; i++); 

is an empty for loop, it's the same as

for (i = 0; i <= 48; i++) {}

What happens is that i is incremented till the condition is false, so when i is > 48, and that is 49, next it will be printed, since i is declared outside the body of the for loop it works good, otherwise i would not be recognized as a variable outside the scope of the for body.

The second expression shown here is actually what you want to do if you have a purposefully built empty for loop.

If you enable warning flags you will be alerted by the compiler.

The next braced statements are made in a new scope, any variable declarations inside this curly braces will not be recognized once the scope ends.

Upvotes: 1

Vlad from Moscow
Vlad from Moscow

Reputation: 311068

To make it clear just remove the braces after the loop because they are redundant. So the program will look like

#include <stdio.h>

int main()
{
    int sub[50], i;

    for (i = 0; i <= 48; i++);

    sub[i] = i;
    printf("%d\n", sub[i]);

    return 0;
}

After executing the loop the variable i will be equal to 49. It is the first value for which the condition of the loop i <= 48 evaluates to false.

So this value 49 is assigned to the element of the array sub with the index 49. This element is outputted in the following statement.

Braces are used to create a new scope for declarations. But in a program like for example this

#include <stdio.h>

int main()
{
    int sub[50], i;

    { for (i = 0; i <= 48; i++); }

    { sub[i] = i; }
    { printf("%d\n", sub[i]); }

    { return 0; }
}

neither declaration is present within each pair of braces (of course except the outermost braces that enclose the body of the function main). So the braces here are redundant and do not change the control flow of the program..

As a result the last program with numerous braces will produce the same result as the first program without the braces.

Pay attention to that this for loop statement

for (i = 0; i <= 48; i++);

has a null sub-statement. That is the semicolon introduces a null sub-statement of the for loop statement.

From the C Standard (6.8.3 Expression and null statements)

3 A null statement (consisting of just a semicolon) performs no operations.

So you may say that the loop in each its iteration executes a null statement that performs no operations.:)

In fact this for statement

for (i = 0; i <= 48; i++);

is equivalent to the following for statement

for (i = 0; i <= 48; i++) {}

So the original program can be also rewritten the following way

#include <stdio.h>

int main()
{
    int sub[50], i;

    for (i = 0; i <= 48; i++) {}

    {
        sub[i] = i;
        printf("%d\n", sub[i]);
    }

    return 0;
}

Upvotes: 1

smac89
smac89

Reputation: 43196

The braces create a new scope, which is not attached to the scope of the for loop.

The output you get is as a result of the new scope being able to see the changes made to i, and therefore is able to print the value of sub[i].

Upvotes: 0

Related Questions