Какая логика стоит за этим кодом C? - PullRequest
0 голосов
/ 28 сентября 2010
for(int i=0 ; i++ ; printf("%d",i));
printf("%d",i);

Выход 1. Если мы сделаем i = 1, то получится абсурдный вывод, а если i = -1, то будет 01. Как работает цикл For?

Ответы [ 8 ]

14 голосов
/ 28 сентября 2010

Тестовая часть цикла for - i++.

Поскольку ++ (или приращение) равно после исправления (записано после переменной, а не перед ней), приращение происходит после , оператор оценивается и тестируется , Тест на 0, который оценивается как FALSE , следовательно, "цикл" существует, даже не будучи запущенным.

Затем вступает в силу пост-исправление ++, изменяющее i с 0 на 1.

Как указывал @paxdiablo, после выхода из цикла i выходит из области видимости. Независимо от того, что печатает окончательный printf, это другой i, объявленный и получивший значение, которое не отображается в вашем коде.


В других сценариях, если вы начнете i с 1, тогда тест всегда будет верным, и каждое число будет распечатано (до тех пор, пока i не переполнится и не вернется к 0).


И, наконец, если i начинается с -1, тест вначале проходит (-1 означает ИСТИНА ), происходит приращение после исправления, превращение -1 в 0 и вывод 0 .

Цикл запускается снова, на этот раз 0 не проходит тест, цикл завершается, происходит приращение после исправления, а другой i (не показанный в вашем коде) распечатывается после окончания цикла.

6 голосов
/ 28 сентября 2010

Цикл for даже не запускается - i равно 0 при тестировании в условии, до увеличения . Кроме того, если i не определено где-то до цикла, код не будет компилироваться, потому что i в printf после цикла не определено.

Откуда ты взял этот код? Это очень гротескный способ написать цикл for, и я бы никогда не использовал его вне конкурса запутанного кодирования.

3 голосов
/ 28 сентября 2010

Он не должен компилироваться, если только не объявлено ранее i.

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

Цикл for имеет три предложения.Первый выполняется в самом начале и больше нигде, и (в C99 и C ++) может быть объявлением.Он устанавливает начальное значение i.

. Второе предложение выполняется перед телом цикла.Если значение равно false, оператор for немедленно заканчивается.Поскольку i является int, единственным ложным значением является 0. В этом случае i++ возвращает текущее значение i и увеличивает его для последующего использования.Следовательно, если i равно 0, цикл for ничего не делает.Если i равно 1, то i будет увеличиваться до тех пор, пока i не станет 0 или что-то еще не произойдет.Это фактически неопределенное поведение, поскольку i является целочисленным типом со знаком, но обычно происходит то, что он будет увеличиваться до максимально положительного значения int, затем превращаться в максимально отрицательный int, а затем увеличиваться доэто 0, и цикл останавливается.Если i начинается с -1, то при первом запуске это не 0, но это будет при втором запуске.

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

Тело цикла for пустое, как показано ; сразу после закрывающей скобки.Это означает, что после выполнения первого предложения выполнение будет чередоваться со вторым и третьим с остановкой всякий раз, когда второе предложение оценивается в 0.

Это очень странный оператор for, в котором неттело цикла и инкремент выполняется во втором предложении, но это допустимо (если нет арифметического переполнения, которое произойдет, если i положительно для начала)Неопределенный i, следующий сразу же, не является.

1 голос
/ 28 сентября 2010

Это похоже на искаженный код. Я не могу поверить, что это намеренно.

Вторая часть оператора for () определяет условие завершения цикла. Если условие оценивается как true, тогда цикл заканчивается, в противном случае он повторяется.

В этом случае вторая часть оператора - i++. Обычно это будет в третьем разделе оператора if (). Вставляя вторую часть, вы заставляете цикл завершаться только в том случае, если i++ оценивается как false, то есть ноль. Поэтому, если i начинается меньше нуля, вы будете получать итерации до тех пор, пока оно не достигнет нуля, в противном случае вы получите цикл infinte.

Как я уже сказал, ++ обычно находится в третьей части оператора, поэтому, на первый взгляд, похоже, что кто-то удалил среднюю часть оператора if (), получил ошибку компиляции и попытался исправить это, заклинив printf () в конце. Грязное.

1 голос
/ 28 сентября 2010

В for(int i=0 ; i++ ; printf("%d",i)); условие теста ложно (поскольку i++ возвращает 0), цикл не будет запущен.

Обратите внимание на точку с запятой после цикла. :)

0 голосов
/ 28 сентября 2010
for(int i=0 ; i++ ; printf("%d",i)); printf("%d",i);

эквивалентно

int i = 0; 

while (i++)
{
   printf("%d",i);
}

printf("%d",i);

Когда i = 0 изначально, i ++ равен 0 (и, следовательно, false), поэтому цикл никогда не будет выполнен.Но мне присваивается значение 1, поэтому последние printf выводят 1.

Когда изначально i = -1, тогда i ++ равен -1 (ненулевой, поэтому true), поэтому выполняется тело цикла.После i ++, i равно 0, поэтому первый printf печатает 0. Теперь мы свели проблему к предыдущему случаю, поэтому остальная часть вывода равна 1. Таким образом, общий вывод равен «01», с 0 и 1находясь рядом друг с другом, потому что вы не поместили пробелы в строку формата printf.

Когда изначально i = 1, цикл выполняется с i = 1, затем i = 2, затемi = 3, ..., затем i = 2147483647 (или что бы то ни было INT_MAX), затем оборачиваемся в i = -2147483648, затем i = -2147483647, затем i = -2147483646 и в конечном итоге обнуляется после печати миллиардов чисел.

0 голосов
/ 28 сентября 2010

++ используется как постинкремент.Таким образом, вы, когда вы проверяете значение i, это будет 0, и вы вообще не входите в цикл.Вне цикла вы печатаете значение i, которое теперь 1

0 голосов
/ 28 сентября 2010

Этот цикл заканчивается, когда i равен 0. Поэтому, если вы начнете выше 0, я буду 0 ... после 2 ^ 31 или 2 ^ 63 итераций.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...