Почему мы должны инициализировать переменную перед ее использованием?

Возможный дубликат:
Что происходит с объявленной, неинициализированной переменной в C? Имеет ли это значение?

Теперь я читаю Teach Yourself C in 21 Days . В главе 3 есть такая заметка:

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

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

Когда объявляется переменная, она указывает на часть памяти.

Доступ к значению переменной даст вам содержимое этой части памяти.

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

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

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

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

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

На стороне заметьте, не доверяйте ни одной книге, которая утверждает, что научила вас X-языку программирования через 21 день. Они лежат, получают себе приличную книгу.

Вы можете использовать переменную, объявленную вне области вашего текущего метода.

Рассмотрим следующее

 int count = 0; while(count < 500) { doFunction(); count ++; } ... void doFunction() { count = sizeof(someString); print(count); } 

В C, используя значения неинициализированных автоматических переменных (нестатические локали и переменные параметров), которые удовлетворяют требованию быть register переменной, является неопределенным поведением, поскольку такие значения переменных могут быть извлечены из регистра, а некоторые платформы могут прервать вашу программу если вы читаете такие неинициализированные значения. Сюда входят переменные типа unsigned char (это было добавлено к более поздней версии C, чтобы разместить эти платформы).

Использование значений неинициализированных автоматических переменных, которые не удовлетворяют требованию быть register переменной, подобно переменным, которые имеют свои адреса, отлично, пока реализация C, которую вы используете, не получила ловушек для используемого типа переменной. Например, если тип переменной является unsigned char , Стандарт требует, чтобы на всех платформах не было ловушечных представлений, хранящихся в таких переменных, и чтение неопределенного значения из него всегда будет иметь успех и не является неопределенным поведением. Такие типы, как int или short , не имеют таких гарантий, поэтому ваша программа может упасть в зависимости от используемой вами реализации C.

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

Для переменных выделенной продолжительности хранения ( malloc …) то же самое относится и к автоматическим переменным, которые не удовлетворяют требованиям для register переменной, поскольку в этих случаях задействованные реализации C должны сделать вашу программу прочитанной из памяти, и не будет сталкиваться с проблемами, в которых чтение регистров может вызывать исключения.

В C значение неинициализированной переменной неопределенно. Это означает, что вы не знаете его значения и может отличаться в зависимости от платформы и компилятора. То же самое справедливо и для таких соединений, как struct и типы union .

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

Как? Примитивные типы могут быть инициализированы из литералов или возвращаемых значений функции.

 int i = 0; int j = foo(); 

Структуры могут быть инициализированы нулями с помощью синтаксиса совокупного синтаксиса:

 struct Foo { int i; int j; } struct Foo f = {0}; 

Рискуя быть педантичным, заявление

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

это неверно. Если бы было лучше высказано:

Не используйте значение неинициализированной переменной.

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

Итак, все в порядке:

 int i ; // uninitialised variable i = some_function() ; // variable is "used" in left of assignment expression. some_other_function( i ) ; // value of variable is used 

хотя когда some_function () называется i не инициализируется. Если вы назначаете переменную, вы определенно «используете» ее (чтобы сохранить возвращаемое значение в этом случае); тот факт, что он не инициализирован, не имеет значения, потому что вы не используете его значение.

Теперь, если вы придерживаетесь

Не используйте значение неинициализированной переменной.

как я предположил, причина этого требования становится очевидной – почему вы принимаете значение переменной, не зная, что она содержит что-то значимое? Тогда может возникнуть вопрос: «почему C не инициализирует auto переменные с известным значением. Возможными ответами на это могут быть:

  • Любое произвольное значение, предоставленное компилятором, не должно быть значимым в контексте приложения – или, что еще хуже, оно может иметь значение, противоречащее фактическому состоянию приложения.

  • C был преднамеренно разработан, чтобы не иметь скрытых накладных расходов из-за его корней в качестве системного языка программирования. Инициализация выполняется только при явной кодировке, поскольку для выполнения требуются дополнительные машинные инструкции и циклы ЦП.

Обратите внимание, что static переменные всегда инициализируются нулем. Языки .NET, такие как C #, имеют концепцию нулевого значения или переменную, которая ничего не содержит и которая может быть явно протестирована и даже назначена. Переменная в C не может содержать ничего , но то, что она содержит, может быть неопределенной, и поэтому код, который использует его значение, будет вести себя недетерминированно.

  • Как установить условную точку останова в Xcode на основе свойства объекта?
  • Почему я не могу назначить массивы как & a = & b?
  • Загадка (в C)
  • Использование более, чем операторов
  • Поиск последовательной битовой строки 1 или 0
  • Отключение политики одного и того же происхождения в Safari
  • Почему возврат 0 необязателен?
  • Как получить длину функции в байтах?
  • Функция gets () в C
  • Когда использовать бит-поля в C?
  • void main () {if (sizeof (int)> -1) printf ("true"); else printf ("false"); ;
  • Interesting Posts

    Корневые файлы Rsync между системами без указания пароля

    Как выбрать подматрицу (не в каком-либо конкретном шаблоне) в Matlab

    Преобразование трапеции в прямоугольник

    Почему macros препроцессора злые и какие альтернативы?

    Восстановление данных из полного формата в разделе NTFS

    ng-app vs. data-ng-app, в чем разница?

    Словарь, в котором значение является анонимным типом в C #

    Любые советы или рекомендации по ускорению обнаружения и инициализации USB-устройств?

    Как я могу преобразовать английские цифры в арабские цифры?

    Маршрутизация: текущий запрос на действие неоднозначен между следующими методами действий

    Активация Windows 10

    Как вы можете сделать что-нибудь полезное без изменчивого состояния?

    Как связаны ALSA и PulseAudio?

    Создание пакетов R с использованием альтернативного GCC

    Windows 7: Любой способ отключить «показать caracter» в свойствах сети WIFI?

    Давайте будем гением компьютера.