Когда я запускаю следующую программу, она печатает мусорное значение:
#include <stdio.h>
int main() {
int a;
printf("%d\n", a);
return 0;
}
Но когда я запускаю этот код, предназначенный для вывода десяти мусорных значений, он просто печатает ноль один раз. Почему он больше не показывает никакого мусора. Я использую компилятор gcc.
#include <stdio.h>
int main() {
int i;
for (i=0; i<=0; i++) {
int a;
printf("%d\n", a);
}
return 0;
}
Я ожидал, что этот код покажет десять разных мусорных значений.
Почему 0 не является мусорным значением?
for (i=0; i<=0; i++)
не будет повторяться десять раз.
И технически значение неинициализированных локальных нестатических переменных является неопределенным.
Результат вызова неопределенного поведения не определен. Все возможно; любой результат так же действителен, как и любой другой.
(1) вы выполняете цикл только один раз (от 0 до 0 включительно), (2) 0 является совершенно ценным мусорным значением (3) что более важно, чтение унитаризованной переменной приводит к неопределенному поведению, с этого момента все возможно (как @ заявил Джонатан Леффлер).
Неинициализированные переменные хранятся в специальных сегментах данных, часто называемых BSS. Раньше эти области были неинициализированы и содержали случайные значения, или, точнее, все, что последним написала предыдущая программа. По соображениям безопасности эти области теперь инициализируются загрузчиком обычно нулями, но также и другими значениями. Однако при программировании следует предполагать неопределённые значения и неопределённое поведение.
Не существует ценности, которая была бы «мусорной ценностью». Фраза «мусорная ценность» — это разговорное выражение, которое неправильно описывает ситуацию, и вам следует избегать его использования.
Когда объект в C не инициализирован, стандарт C говорит, что он имеет «неопределенное значение». Опять же, не существует «неопределенной» ценности. Лучше сказать, что значение не определено. Это означает не только то, что ни одно правило в стандарте C не определяет, каким должно быть значение, но и то, что объект вообще не обязательно имеет фиксированное значение. Попытка использовать значение объекта может привести к получению разных значений в разное время.
Когда программа печатает «0», это соответствует правилам стандарта C, поскольку нет требования выводить какое-либо конкретное значение. Когда выводится неопределенное значение, может быть напечатано любое значение этого типа. Ноль — это значение типа int
, поэтому оно удовлетворяет критериям так называемого «неопределённого значения» или «мусорного значения».
Программа печатает только одно значение, поскольку for (i=0; i<=0; i++)
выполняет итерацию только один раз. Он устанавливает i
в ноль, выполняет тело цикла и увеличивает i
до единицы. Тогда тест i<=0
ложный, поэтому цикл останавливается.
В этом случае все поведение вашей программы не определено из-за специального правила, которое гласит, что использование значения неинициализированного объекта с автоматической продолжительностью хранения, которая могла бы быть объявлена, имеет неопределенное поведение (C 2018 6.3.2.1 2). Таким образом, стандарт C вообще не требует, чтобы ваша программа выводила какое-либо значение. Он может выйти из строя или завершить работу, ничего не печатая, или печатать бесконечно, или выполнять другие действия.
I expected this code to show ten different garbage values.
почему?