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

Например:

main()
{
   char rx_char;
   :
   :
   rx_char = get_char();

}

Мой коллега просит меня инициализировать rx_char, но я не понимаю почему. Кто-нибудь может указать причину?

c gcc
1
user1932637 22 Май 2014 в 00:15

4 ответа

Лучший ответ

«Инициализация каждой переменной при ее объявлении, даже если значение бессмысленно» - это школьный пример поведения культа карго . Это совершенно бессмысленное требование, которого следует по возможности избегать. Во многих случаях бессмысленный инициализатор не намного лучше случайного неинициализированного значения. В тех случаях, когда он действительно может «спасти положение», он делает это, заметая проблему под ковер, т. Е. скрывая ее. Скрытые проблемы всегда хуже всего. Когда в коде есть проблема, всегда лучше, чтобы она проявилась как можно быстрее, даже если код дает сбой или ведет себя беспорядочно.

Кроме того, такие требования могут препятствовать оптимизации компилятора, рассылая в компилятор ложную информацию о времени жизни эффективного значения, связанном с переменной. Оптимизатор может рассматривать неинициализированную переменную как несуществующую, тем самым экономя ценные ресурсы (например, регистры ЦП). Чтобы получить такие же знания о переменной, инициализированной бессмысленным значением, оптимизатор должен понять, что это действительно бессмысленно, что обычно является более сложной задачей.

Эту же проблему должен решить человек, читающий код, что затрудняет читаемость. Человек, незнакомый с кодом, не может сразу сказать, является ли конкретный инициализатор значимым (т.е. приведенный ниже код полагается на начальное значение) или бессмысленным (т.е. предоставлен бездумно последователем вышеупомянутого культа карго).

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

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

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

5
AnT 21 Май 2014 в 23:24

С современными компиляторами, часто выдающими предупреждение об использовании неинициализированных переменных, я бы предпочел не инициализировать какое-то фиктивное значение. Затем, если кто-то случайно использует переменную перед инициализацией, вы получите предупреждение, вместо того, чтобы тратить X времени на отладку и обнаружение ошибки.

2
MicroVirus 21 Май 2014 в 21:06

Хорошая практика - инициализировать ваши переменные, даже если они просто устанавливают для них "нулевой" эквивалент типа. Если кто-то другой приходит и хочет отредактировать этот код, и использует rx_char до того, как вы его инициализировали, он получит недетерминированное поведение. Значение rx_char будет зависеть от вещей, находящихся вне вашего контроля. Некоторые компиляторы 0 инициализируют переменные, но вы не должны зависеть от этого!

Инициализируя его при объявлении, вы гарантируете детерминированное поведение. Что в целом легче отлаживать, чем иметь rx_char что-то совершенно случайное, что потенциально могло бы быть, если бы вы оставили его неинициализированным.

main() {
    char rx_char;
    //Some stuff
    char your_coworkers_char = rx_char;
    //Some other stuff
    rx_char = get_char();
    putchar(your_cowowarers_char); //Potentially prints randomness!
}

Это, возможно, оптимально, если вы не работаете с компиляторами супер-старого стиля, вас это должно устроить.

main() {
    //some stuff
    char rx_char = get_char();
    putchar(your_cowowarers_char); //Potentially prints randomness!
}
0
ChrisCM 21 Май 2014 в 21:12

Кто-нибудь мог указать причину?

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

...

Большинство стандартов кодирования ориентированы не только на будущее, но и на то, что происходит сегодня.

Сегодня да, нет никакой разницы, есть ли у вас char rx_char или char rx_char = 0. Но что произойдет в будущем, если кто-то удалит строку rx_char=getchar()? Тогда rx_char - случайное неинициализированное значение. Если rx_char равен 0, тогда у вас все равно будет ошибка, но она не будет случайной.

-1
Andy Lester 21 Май 2014 в 20:48