for (;;) { //Something to be done repeatedly }
Я видел, что этот вид вещи использовал много, но я думаю, что это довольно странно... Не был бы это быть намного более ясным сказать
while(true)
, или что-то вдоль тех строк?Я предполагаю, что (как причина для многих-программистов обратиться к загадочному коду) это - крошечное поле быстрее?
Да ведь и это действительно стоит того? Если так, почему не только определяют его этот путь:
#define while(true) for(;;)
См. также: Который быстрее: в то время как (1) или в то время как (2)?
Я предполагаю, что while (true) более читабельно, чем for (;;) - похоже, что программист что-то упустил в цикле for :)
и кого волнует, какой из них быстрее
Я не могу представить, что достойный компилятор сгенерирует какой-либо другой код. Даже если бы это было так, не было бы никакого способа определить без тестирования конкретного компилятора, который был бы более эффективным.
Однако я предлагаю вам предпочесть для (;;)
по следующим причинам:
ряд компиляторов, которые я использовал, будут генерировать предупреждение о постоянном выражении для while (true) с соответствующими настройками уровня предупреждения .
в вашем примере макрос TRUE может быть определен не так, как вы ожидаете
существует много возможных вариантов бесконечного цикла while, например while (1)
, while (true)
, в то время как (1 == 1)
и т.д .; поэтому для (;;)
, вероятно, приведет к большей согласованности.
Это определенно не быстрее ни в одном нормальном компиляторе. Оба они будут объединены в безусловные прыжки. Версию for легче набирать (как сказал Нил), и она будет понятна, если вы понимаете синтаксис цикла for.
Если вам интересно, вот что дает мне gcc 4.4.1 для x86. Оба используют инструкцию x86 JMP .
void while_infinite()
{
while(1)
{
puts("while");
}
}
void for_infinite()
{
for(;;)
{
puts("for");
}
}
компилируется в (частично):
.LC0:
.string "while"
.text
.globl while_infinite
.type while_infinite, @function
while_infinite:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
.L2:
movl $.LC0, (%esp)
call puts
jmp .L2
.size while_infinite, .-while_infinite
.section .rodata
.LC1:
.string "for"
.text
.globl for_infinite
.type for_infinite, @function
for_infinite:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
.L5:
movl $.LC1, (%esp)
call puts
jmp .L5
.size for_infinite, .-for_infinite
Я предпочитаю вместо (;;)
по двум причинам.
Во-первых, некоторые компиляторы выдают предупреждения на while (true)
(что-то вроде «условие цикла постоянно»). Всегда полезно избегать предупреждений.
Во-вторых, я думаю, что for (;;)
более понятен и информативен.
Мне нужен бесконечный цикл. Он буквально не имеет условий, он ни от чего не зависит. Я просто хочу, чтобы это продолжалось вечно, пока я не сделаю что-нибудь, чтобы вырваться из него.
Тогда как с в то время как (правда)
, что ж, при чем тут правда? Меня не интересует цикл, пока истина не станет ложью, что буквально говорит эта форма (цикл, пока истина - истина). Я просто хочу зациклить.
И нет абсолютно никакой разницы в производительности.
Благодаря Деннису Ричи
я начал использовать для (;;)
, потому что именно так Деннис Ричи делает это в K&R, и при изучении нового языка я всегда стараюсь подражать умным ребятам.
Это идиоматический C / C ++. Вероятно, в конечном итоге будет лучше привыкнуть к этому, если вы планируете много делать в пространстве C / C ++.
Ваш #define
не будет работать, поскольку объект #define'd должен выглядеть как идентификатор C.
Все современные компиляторы будут генерировать один и тот же код для двух конструкций.
Цикл «навсегда» популярен во встроенных системах в качестве фонового цикла.Некоторые люди реализуют это как:
for (; ;)
{
// Stuff done in background loop
}
А иногда это реализуется как:
while (TRUE /* or use 1 */)
{
// Stuff done in background loop
}
И еще одна реализация:
do
{
// Stuff done in background loop
} while (1 /* or TRUE */);
Оптимизирующий компилятор должен генерировать такой же или подобный ассемблерный код для этих фрагментов. Одно важное замечание: время выполнения циклов не имеет большого значения, поскольку эти циклы продолжаются бесконечно, и больше времени тратится на раздел обработки.
while(true)
генерирует предупреждение в Visual Studio (условие постоянно). В большинстве мест, где я работал, производственные сборки с предупреждениями компилируются как ошибки. Поэтому
for(;;)
предпочтительнее.
Я видел, что некоторые люди предпочитают его, потому что у них есть #define где-то вроде этого:
#define EVER ;;
Что позволяет им писать так:
for (EVER)
{
/* blah */
}
Не просто известный шаблон, а стандартная идиома в C (и C++)
Какой из способов быстрее - это вопрос личных предпочтений. Лично я наборщик текста и никогда не смотрю на клавиатуру во время программирования - я могу набрать все 104 клавиши на клавиатуре.
Я считаю, что быстрее набирать "while (TRUE)".
Я мысленно добавил несколько измерений движения пальцев и просуммировал их. "for (;;)" имеет примерно 12 клавиш перемещения назад и четвертое (между клавишами Home и клавишами, а также между клавишами Home и клавиша SHIFT) «while (TRUE)» имеет примерно 14 клавиш для перемещений назад и на четвертую позицию.
Однако я гораздо менее подвержен ошибкам при вводе последнего. Я мысленно думаю словами за раз, поэтому я нахожу, что быстрее набирать такие вещи, как «nIndex», чем акронимы, такие как «nIdx», потому что на самом деле мне приходится мысленно произносить буквы, а не произносить их в уме и позволять пальцам автоматически -введите слово (например, езда на велосипеде)
(My TypingTest.com benchmark = 136 WPM)
Лично я использую for (;;)
, потому что в нем нет никаких чисел, это просто ключевое слово. Я предпочитаю его while (true)
, while (1)
, while (42)
, while (!0)
и т.д. и т.п.
Нет никакой разницы в смысле генерируемого машинного кода.
Однако, чтобы противостоять тенденции, я бы сказал, что форма while (TRUE) гораздо более читабельна и интуитивно понятна, чем для (;;), и что удобочитаемость и ясность являются гораздо более важными причинами для рекомендаций по кодированию, чем любые другие причины, которые я слышал в пользу подхода for (;;) (я предпочитаю основывать свои рекомендации по кодированию на веских аргументах и / или доказательствах эффективности самостоятельно).
Все хорошие ответы - поведение должно быть точно таким же.
ОДНАКО - Просто предположим, что это имело значение. Предположим, на одну итерацию приходилось еще 3 инструкции.
Стоит ли вам заботиться?
ТОЛЬКО если то, что вы делаете внутри цикла, почти ничего , что почти никогда не имеет значения.
Я хочу сказать, что есть микрооптимизация и макрооптимизация. Микрооптимизация похожа на «стрижку, чтобы похудеть».
Я лично предпочитаю для (;;)
идиомы (которая будет компилироваться в тот же код, что и while (TRUE)
.
Использование while (TRUE)
может быть более читаемым в каком-то смысле, я решил использовать идиому для (;;)
, потому что она выделяется .
Конструкция бесконечного цикла должна быть легко заметить или вызвать в коде, и я лично считаю, что стиль for (;;)
делает это немного лучше, чем while (TRUE)
или while (1)
.
Кроме того, я напоминаю, что некоторые компиляторы выдают предупреждения, когда управляющее выражение цикла while является константой. Я не думаю, что это происходит слишком часто, но для меня достаточно одной возможности ложных предупреждений. чтобы избежать этого.
Что насчет (если ваш язык поддерживает это):
start:
/* BLAH */
goto start;