Где я могу юридически объявить переменную в C99? - PullRequest
33 голосов
/ 23 февраля 2010

Когда я впервые познакомился с C, мне сказали всегда объявлять мои переменные в верхней части функции. Теперь, когда я хорошо понимаю язык, я сосредотачиваю свои усилия на стиле кодирования, особенно ограничивая область действия моих переменных. Я прочитал о преимуществах ограничения объема и наткнулся на интересный пример. Видимо, C99 позволяет вам сделать это ...

for (int i = 0; i < 10; i++)
{
   puts("hello");
}

Я думал, что область видимости переменных ограничена самой внутренней , окружающей фигурные скобки { }, но в приведенном выше примере int i, по-видимому, ограничена в объеме фигурными скобками цикл for, даже если он объявлен вне их.

Я попытался расширить приведенный выше пример с помощью fgets(), чтобы сделать то, что мне показалось чем-то похожим, но оба из них дали мне синтаксическую ошибку.

fgets(char fpath[80], 80, stdin); * См. Примечание **

fgets(char* fpath = malloc(80), 80, stdin);

Итак, где именно допустимо объявлять переменные в C99? Был ли пример цикла for исключением из правила? Это относится и к петлям while и do while?

* Примечание **: Я даже не уверен, что это будет синтаксически правильно, даже если бы я мог объявить там массив символов, так как fgets() ищет указатель на символ не указатель на массив 80 символов . Вот почему я попробовал malloc() версию.

Ответы [ 3 ]

36 голосов
/ 23 февраля 2010

В C99 вы можете объявлять свои переменные там, где они вам нужны, точно так же, как C ++ позволяет вам это делать.

void somefunc(char *arg)
{
    char *ptr = "xyz";
    if (strcmp(arg, ptr) == 0)
    {
        int abc = 0;    /* Always could declare variables at a block start */

        somefunc(arg, &ptr, &abc);

        int def = another_func(abc, arg);   /* New in C99 */
        ...other code using def, presumably...
    }
}
  • Вы можете объявить переменную в управляющей части цикла for:

    for (int x = 0; x < 10; x++)    /* New in C99 */
    
  • Нельзя объявить переменную в управляющей части цикла while или оператора if.

  • Вы не можете объявить переменную в вызове функции.
  • Очевидно, что вы можете (и всегда могли) объявлять переменные в блоке после любого цикла или оператора if.

Стандарт C99 гласит:

6.8.5.3. Для выписки

Заявление

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

ведет себя следующим образом: выражение-выражение-2 является управляющим выражением, которое оценивается перед каждым выполнением тела цикла. Выражение выражение-3 является оценивается как пустое выражение после каждого выполнения тела цикла. Если пункт-1 является декларация, область действия любых переменных, которые она объявляет, является остальной частью весь цикл, включая два других выражения; достигается в порядке исполнения до первой оценки контрольного выражения. Если предложение-1 является выражением, оно оценивается как пустое выражение перед первой оценкой управляющего выражения.

8 голосов
/ 23 февраля 2010

Первое, что я хотел бы отметить, это то, что вы не должны путать

for (int i = 0; i < 10; i++) {
    puts("hello");
}

и

fgets(char* fpath = malloc(80), 80, stdin);

Первый - это структура управления, а второй - вызов функции. Управляющая структура оценивает текст внутри ее parens () совсем не так, как вызов функции.

Во-вторых, я не понимаю, что вы пытаетесь сказать:

компилятор немедленно выдаст вам ошибку, если вы попытаетесь использовать i внутри тела цикла for.

Код, который вы перечислили для цикла for, является очень распространенной структурой в C, и переменная "i" действительно должна быть доступна внутри тела цикла for. Т.е. должно работать следующее:

int n = 0;
for (int i = 0; i < 10; i++) {
    n += i;
}

Я неправильно понимаю, что вы говорите?

2 голосов
/ 24 февраля 2010

Суть вашей путаницы в for / fgets заключается в том, что, хотя "включающая область управления фигурными скобками" является правильным правилом в C в большинстве случаев, есть другое правило относительно области действия в C99 (заимствовано из C ++) который говорит, что переменная, объявленная в прологе управляющей структуры (т. е. for, while, if), находится в области видимости в теле структуры (и не находится в области видимости вне тела).

...