Значение по умолчанию для не инициализированных переменных

Я читаю этот урок об отладке. Я вставил факториал в мой архив .c:

#include  int main() { int i, num, j; printf ("Enter the number: "); scanf ("%d", &num ); for (i=1; i<num; i++) j=j*i; printf("The factorial of %d is %d\n",num,j); } 

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

Я думал, что это может быть связано с другой версией C, но руководство – с 2010 года.

Почему я всегда вижу 0 вместо стоимости мусора?

Как стандарт проекта C99, так и стандарт проекта C11 говорят, что значение неинициализированной автоматической переменной является неопределенным, из стандарта стандартного раздела c99 6.2.4 Длительность хранения объектов , упомянутых в параграфе 5 ( подчеркивается мной ):

Для такого объекта, который не имеет тип массива переменной длины, его время жизни продолжается от входа в блок, с которым он связан, до тех пор, пока выполнение этого блока не закончится каким-либо образом. (Ввод закрытого блока или вызов функции приостанавливает, но не завершает выполнение текущего блока.) Если блок введен рекурсивно, каждый экземпляр объекта создается каждый раз. Начальное значение объекта является неопределенным. Если для объекта задана инициализация, она выполняется каждый раз, когда декларация достигается при выполнении блока; в противном случае значение становится неопределенным при достижении объявления.

проект стандарта определяет неопределенный, как:

либо неопределенное значение, либо ловушечное представление

и неопределенное значение определяется как:

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

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

В стандарте говорится, что это не определено в одном из примеров в разделе 6.5.2.5 литералы, параграф 17, который гласит:

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

это также рассматривается в Annex J.2 Неопределенное поведение :

Значение объекта с автоматической продолжительностью хранения используется, пока оно неопределено (6.2.4, 6.7.8, 6.8).

В некоторых очень конкретных случаях вы можете сделать некоторые outlookы о таком поведении, презентация Deep C входит в некоторые из них. Эти виды экспертизы должны использоваться только как инструмент для дальнейшего понимания того, как работают системы и которые никогда не должны приближаться к производственной системе.

Вам нужно инициализировать j до 1. Если j окажется равным нулю, ответ всегда будет равен нулю (один тип мусора). Если j имеет ненулевое значение, вы получите разный мусор. Использование неинициализированных переменных – неопределенное поведение; «undefined» не исключает, что в тестах, которые вы делали до сих пор, всегда равен нулю.

В некоторых системах их память установлена ​​на 0 (например, Mac OS), поэтому ваша переменная часто будет содержать 0, когда вы ее инициализируете, но это плохая практика, которая приведет к нестабильным результатам.

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

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

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