с помощью ";" в конце оператора for, но код все еще выполняется - PullRequest
1 голос
/ 19 апреля 2020
#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;
}

Почему вывод 49?

Я думаю, что он не должен выполнять функцию printf.

Ответы [ 4 ]

3 голосов
/ 19 апреля 2020

Ваша программа имеет ошибку classi c: строка оператора for заканчивается ;, в результате чего for имеет пустое тело, а следующий блок выполняется безоговорочно один раз с i с последним значение в конце l oop, ie 49.

Оператор for заканчивается на ;, а { в следующей строке начинает отдельный блок, не связанный в оператор for, который выполняется безоговорочно.

Итак, ваша программа эквивалентна:

#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;
}

Я не знаю, специально ли вы добавили ;, но если вы сделали это по ошибке, обратите внимание, что стиль classi c K & R делает этот тип ошибки гораздо менее вероятным:

#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;
}

Используя синтаксис c99 new for, вы определяете i в for начальное предложение и компилятор поймает ошибку:

#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;
}

Создание пустых циклов преднамеренно с помощью только конечного ; в конце строки for() сбивает с толку и подвержено ошибкам. Компиляторы могут пометить это предупреждением, если настроены на более высокий уровень предупреждения, что, кстати, является очень хорошей практикой для обнаружения глупых ошибок (ie: gcc -Wall -Werror или clang -Weverything -Werror).

Если вы хотите пустое значение body, я бы порекомендовал этот синтаксис:

/* find the last node of the list */
if (list) {
    for (cur = list; cur->next; cur = cur->next)
        continue;
    //...
}
1 голос
/ 19 апреля 2020

Чтобы было понятно, просто удалите фигурные скобки после l oop, потому что они избыточны. Таким образом, программа будет выглядеть как

#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;
}

После выполнения l oop переменная i будет равна 49. Это первое значение, для которого условие l oop i <= 48 оценивается как ложное.

Так что это значение 49 присваивается элементу массива sub с индексом 49. Этот элемент выводится в следующем операторе.

Скобки используются для создания новой области видимости для объявлений. Но в такой программе, как, например, эта

#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; }
}

, ни одна декларация не присутствует в каждой паре фигурных скобок (конечно, кроме самых внешних фигурных скобок, которые заключают тело функции main). Таким образом, фигурные скобки здесь избыточны и не изменяют поток управления программой.

В результате последняя программа с многочисленными фигурными скобками выдаст тот же результат, что и первая программа без фигурных скобок.

Обратите внимание на то, что оператор l oop

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

содержит нулевой под-оператор. То есть точка с запятой вводит нулевой подоператор оператора for l oop.

Из стандарта C (6.8.3 Выражения выражения и нулевые операторы)

3 Пустой оператор (состоящий только из точки с запятой) не выполняет никаких операций.

Таким образом, вы можете сказать, что l oop в каждой своей итерации выполняет нулевой оператор, который не выполняет никаких операций .:)

Фактически это для оператора

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

эквивалентно следующему для оператора

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

Таким образом, исходная программа также может быть переписана следующим образом

#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;
}
1 голос
/ 19 апреля 2020
for (i = 0; i <= 48; i++); 

- пустое значение для l oop, это то же самое, что и

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

. Случается, что i увеличивается до тех пор, пока условие не станет ложным, поэтому, когда i равно > 48, то есть 49, затем он будет напечатан, так как i объявлен вне тела для l oop, он работает хорошо, иначе i не будет распознан как переменная вне области видимости. of for body.

Второе выражение, показанное здесь, на самом деле то, что вы хотите сделать, если у вас специально построено пустое значение для l oop.

Если вы включите флаги предупреждения, вы будете Оповещение компилятором.

Следующие фигурные выражения сделаны в новой области видимости, любые объявления переменных внутри этих фигурных скобок не будут распознаны после окончания области действия.

0 голосов
/ 19 апреля 2020

Скобки создают новую область видимости, которая не привязана к области видимости для l oop.

Вывод, который вы получаете, является результатом того, что новая область видимости может видеть изменения, внесенные в i, и, следовательно, может печатать значение sub[i].

...