2017-02-18 13 views
2
  1. Преимущества подхода 1 является немного меньшим размером файла из-за менее текстовых символов в исходном коде:Каков лучший способ объявить фиктивные переменные для вложенных циклов?

    int i, j; 
    for (i = 0; i < numRows; i++) 
        for (j = 0; j < numCols; j++) 
        //<some code here> 
    
  2. Преимуществом подхода 2 является меньшей видимостью локальных переменными.

    int i; 
    for (i = 0; i < numRows; i++) 
    { 
        int j; 
        for (j = 0; j < numCols; j++) 
        //<some code here> 
    } 
    

Даже если различия в оптимизации ничтожны в сегодняшних современных компьютеров, которые подход считается «лучше» код?


Редактировать, чтобы уточнить, что этот вопрос не является дубликатом:

Этот вопрос основан на текущем стандарте C11, который не позволяет синтаксис, как это:

for (int i = 0; i < numRows; i++) 

В C++ и C99, этот синтаксис вполне приемлем, тогда как C11 не допускает объявления переменных внутри оператора for.


Редактировать, чтобы исправить дезинформацию:

Я думал, что я использовал C11, потому что я недавно скачал компилятор из CodeBlocks, так вот почему я сказал, C11 не допускает объявления переменных внутри for заявления. Но, оказывается, я на самом деле использовал C90, что стало причиной моих проблем.

+0

Я считаю, что компиляции будут эквивалентны, то есть, вероятно, лучше использовать второе, поскольку это предотвратит случайное использование j вместо i во внешнем цикле. Я не собираюсь публиковать это как ответ, хотя, поскольку у кого-то, более опытного с C, будет лучший ответ. –

+0

см. Это http://stackoverflow.com/questions/7959573/declaring-variables-inside-loops-good-practice-or-bad-practice-2-parter – danishansari

+1

Возможный дубликат [Объявление переменных внутри циклов, хорошей практики или плохая практика? (2 партера)] (http://stackoverflow.com/questions/7959573/declaring-variables-inside-loops-good-practice-or-bad-practice-2-parter) – tod

ответ

5

Для чистой компактности и ограничения объем, я бы использовал:

for (size_t i = 0; i < numRows; i++) { 
    for (size_t j = 0; j < numCols; j++) { 
    //<some code here> 
    } 
} 

Обратите внимание на использование size_t для показанных индексов массива. Тип size_t представляет собой целочисленный тип unsigned, гарантирующий, что он может удерживать любой индекс массива. Просто вопрос стиля, но я бы также предложил использовать фигурные скобки вокруг всех тел петли. Это значительно снижает вероятность того, что вы нарушите свой код с неизбежными обновлениями и изменениями.

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

+0

Привет, Дэвид. Спасибо за ваш ответ. Но, как я упомянул в другом комментарии к ответу Питера, меня беспокоят объявления переменных внутри операторов for. В то время как C99 разрешает ваш синтаксис, из того, что я читал, C11 не позволяет объявлять переменные внутри круглых скобок for-loop. –

+0

@ пятницаSky-- C11 действительно позволяет. Где вы это читали? [Из проекта стандарта C11] (http: // port70.net/~ nsz/c/c11/n1570.html # 6.8.5.3): «Если предложение-1 является объявлением, область действия любых идентификаторов, которые он объявляет, является остатком объявления и всего цикла, включая другие два выражения .... » –

+0

@ FridaySky-- использование переменных с петлевой областью в C (когда это имеет смысл) считается лучшей практикой для многих, возможно, даже самых профессиональных программистов. –

-1

Второй метод является лучшим методом, как

  1. Он может использовать низкую память
  2. позволяет использовать тот же переменное снова, если это необходимо в любом другом цикле
+1

Будет ли это использовать меньше памяти? Я понимаю, что большинство компиляторов автоматически перемещают переменную внутри цикла. –

1

Это, кажется, быть вопрос вкуса, а не имея каких-либо конкретных ответов, но я дам вам мое мнение:

С учетом нынешних компьютеров, экономя пару символов исходного кода слишком тривиально, чтобы даже думать о , На самом деле, я думаю, я бы сказал, что даже когда я изучал C на VAX 11/780 в 1976 году.

Я бы предпочел второй пример, поскольку текущее предпочтение заключается в том, чтобы объявить переменную как можно ближе к первому использованию. В C++ можно даже поместить объявления переменных цикла внутри для операторов:

for (int i = 0; i < numRows; i++) { 
    for (int j = 0; j < numCols; j++) { 
     ... 
    } 
} 

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

+2

C99 допускает 'for (int i = ...'. Нет необходимости в C++ – rici

+0

Спасибо. Я пробовал искать спецификацию ANSI C, но я получил версию 1988. В любом случае, эта спецификация написана для авторов компиляторов, а не для пользователей Надеемся когда-нибудь найти эквивалент ANSI C книги Harbison & Steele, «C: Справочное руководство». (Также для версии C++.) –

1

Ни один из подходов не является предпочтительным.

Два общих правила кодирования: (1), чтобы гарантировать, что переменная не существует дольше, чем она требуется, и (2) не использовать переменную более чем для одной вещи. Следуя таким рекомендациям, вы уменьшаете (часто, но не всегда, исключаете) случайное использование переменной таким образом, чтобы это не было предназначено, и, следовательно, помогает избежать тонких ошибок программирования.

В вашем первом случае как i, так и j продолжают существовать до конца охватывающей области - что означает, что они существуют после завершения циклов. Это максимизирует шансы последующего кода (в том охватывающем объеме), случайно повторного использования i или j для другой цели (например, когда целью является использование другой переменной). Такие ошибки часто трудно найти.

Второй случай имеет ту же проблему, за исключением только i. Однако даже одна переменная с такой проблемой - плохая новость.

Я бы, вероятно, использовать конструкцию как

// unintentionally using i or j here will cause a compilation error 

for (int i = 0; i < numRows; i++) 
{ 
    // unintentionally using j here will cause a compilation error 

    for (int j = 0; j < numCols; j++) 
    { 
     //<some code here> 
    } 

    // unintentionally using j here will cause a compilation error 
} 

// unintentionally using i or j here will cause a compilation error 

(комментарии, которые я уже вставленные сделать точку сделать это более нечитаемым, но такие комментарии как правило, не требуется на практике).

Это гарантирует, что ни один i не j не существует за пределами внешнего контура. Это также означает, что j не может быть случайно использован во внешнем цикле. Практически легко набрать i, когда j предназначен (и наоборот) - например, они близки друг к другу на клавиатуре QWERTY. i и j также выглядят совершенно аналогично визуально, поэтому визуальные проверки кода часто пропускают такие ошибки. Однако, используя такой подход, COMPILER обнаружит такие опечатки. Учитывая выбор, лучше иметь компилятор, забирающий ошибки, а не для человека, чтобы иметь проблемы с их поиском.

Конечно, это не мешает злоупотребления или взаимообмен i и j во внутреннем цикле - но это одна из причин, что рекомендации часто поощряют использование более информативных имен, чем i и j - злоупотребление визуально разных имен легче простой смертный для обнаружения.

+0

Привет, Питер. Спасибо за ваш ответ. Моя забота о вашей конструкции что некоторые компиляторы C не допускают объявления переменных внутри круглых скобок for-loop. Однако для других языков, таких как Java, ваша конструкция будет очень идеальной. –

+0

Не беспокойтесь о моем предыдущем комментарии. Оказывается, я использовал компилятор такой же старый, как C90, хотя я только установил компилятор только год назад. –