Я не знаю термина «мусор».
«Мусор» - это небрежный язык. По большей части, люди подразумевают под этим следующее: «Мы не контролируем то, что есть». Это не означает, что они случайны (никто не пытается поместить туда случайные данные) или что это мусор (это не обязательно данные, не имеющие значения или значения). (Учтите, что злоумышленник, ищущий дефекты в программе, может найти неинициализированные данные, и эти данные могут фактически содержать ключи к номерам банковских счетов, паролям, криптографическим ключам или другим данным - опасно предполагать, что неинициализированные данные - это просто мусор. )
В C я слышал, что значение спецификатора Register по умолчанию - мусор.
С очень простым компилятором или некоторыми компиляторами с отключенной оптимизацией , программа может быть переведена буквально так, что для int x
будет назначено некоторое пространство памяти, и использование значения x
загружает данные из этой памяти, а для register int y
назначается некоторый регистр, и с использованием значения y
использует данные из этого регистра. Однако в современных компиляторах, использующих оптимизацию, этого обычно не происходит.
Вместо этого C исходный код представляет программу, которая выполняется на абстрактном компьютере. В абстрактной модели эта программа загружает данные, например, из памяти, назначенной x
. Однако компилятор не генерирует инструкции для реализации этой программы. Компилятор анализирует программу, чтобы выяснить, как получить те же результаты, что и программа, но быстрее.
Для этой цели единственными результатами, которые имеют значение как «те же результаты», являются те, которые определены C стандартное соответствие. Вот эти результаты:
- Вывод программы, включая все данные, записанные в файлы.
- Взаимодействие ввода и вывода (поэтому запросы, записанные в стандартный вывод, должны появиться до того, как будет принят ввод , если абстрактная программа написана таким образом).
- Доступ к
volatile
объектам оценивается строго в соответствии с правилами абстрактной машины.
Помимо этого, компилятор может реорганизовать программу по своему усмотрению. Когда значение x
используется в выражении, компилятору не нужно загружать его из памяти, если у него уже есть копия в регистре из некоторой предыдущей работы. Или, если требуется 6*x
, а у компилятора этого нет или x
под рукой, но у него есть копия 3*x
, то компилятор может просто взять 3*x
и удвоить его вместо загрузки * 1036. * по памяти вычислить 6*x
. Возможны и гораздо более сложные оптимизации.
Что произойдет, если вы никогда не инициализируете x
, будь то в памяти или в регистре? Стандарт C не говорит, что происходит (с некоторыми оговорками). Это означает, что программа абстрактного компьютера не предназначена для каких-либо конкретных действий. Тогда оптимизатор в компиляторе может извлечь из этого все, что захочет. Если в выражении используется x
, оптимизатору вообще не нужно загружать его из памяти, и, если x
номинально назначено регистру, компилятор не должен использовать этот регистр для x
. Это потому, что если x
никогда не инициализировался, тогда правила стандарта C не говорят, что он имеет какое-то конкретное значение. Таким образом, не имеет значения, имеет ли память, назначенную x
, содержимое 1234, но компилятор использует какой-то несвязанный регистр, который содержит 5678, потому что правила стандарта C говорят, что в памяти могло быть 5678 . Что касается компилятора, использование неконтролируемых данных из регистра аналогично использованию неконтролируемых данных из памяти, поэтому нет причин беспокоиться о фактической загрузке данных из памяти; это было бы пустой тратой времени.
Это обзор. В стандарте C есть определенные правила c о:
- , когда значение может быть некоторым неопределенным значением, но не может быть перехвачено (генерировать исключение и завершать вашу программу или делать другие вещи),
- когда значение может быть не только некоторым неопределенным значением, но и другим значением каждый раз, когда вы его используете,
- при использовании неинициализированного значения может вызвать ловушку.