Инициализация переменных в C - PullRequest
20 голосов
/ 02 ноября 2011

Я знаю, что иногда, если вы не инициализируете int, вы получите случайное число, если напечатаете целое число.

Но инициализация всего в ноль кажется глупой.

Я спрашиваю, потому что я комментирую свой проект C, и я довольно прямолинейен в отношении отступов, и он полностью компилируется (90/90, спасибо Stackoverflow), но я хочу получить 10/10 о баллах стиля.

Итак, вопрос: когда уместно инициализировать, а когда просто объявить переменную:

int a = 0;

vs.

int a;

Ответы [ 10 ]

34 голосов
/ 02 ноября 2011

В некоторых случаях не следует инициализировать переменную:

  1. Когда у него статическая продолжительность хранения (static ключевое слово или глобальная переменная), и вы хотите, чтобы начальное значение было нулевым. Большинство компиляторов фактически хранят нули в двоичном файле, если вы явно инициализируете, что обычно является пустой тратой пространства (возможно, огромной тратой для больших массивов).
  2. Когда вы будете немедленно передавать адрес переменной другой функции, которая заполняет ее значение. Здесь инициализация - просто пустая трата времени и может сбить с толку читателей кода, которые задаются вопросом, почему вы храните что-то в переменной, которая должна быть перезаписана.
  3. Когда значимое значение для переменной не может быть определено, пока последующий код не завершит выполнение. В этом случае активно вредно инициализировать переменную с помощью фиктивного значения, такого как ноль / NULL, поскольку этот не позволяет компилятору предупреждать вас , если у вас есть пути кода, где значимое значение никогда не назначается. Компиляторы хорошо предупреждают вас о доступе к неинициализированным переменным, но не могут предупредить вас о переменных «все еще содержит фиктивные значения».

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

24 голосов
/ 02 ноября 2011

Правило, которое еще не упоминалось, таково: когда переменная объявляется внутри функции, она не инициализируется, а когда она объявляется в статической или глобальной области видимости, она устанавливается равной 0:

int a; // is set to 0

void foo() {
  int b;  // set to whatever happens to be in memory there
}

Однако - для удобства чтения я обычно инициализирую все во время объявления.

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

5 голосов
/ 02 ноября 2011

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

Что касается переменных-членов, вам следует инициализировать их в конструкторе вашего класса.

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

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

5 голосов
/ 02 ноября 2011

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

Если при инициализации вам нужно ненулевое значение, то вам всегда следует явно инициализировать.

4 голосов
/ 02 ноября 2011

Я могу вспомнить пару причин из головы:

  1. Когда вы собираетесь инициализировать его позже в своем коде.

    int x;
    
    if(condition)
    {
        func();
        x = 2;
    }
    else
    {
       x = 3;
    }
    anotherFunc(x); // x will have been set a value no matter what
    
  2. Когда вам нужно немного памяти для хранения значения, установленного функцией или другим фрагментом кода:

    int x;  // Would be pointless to give x a value here
    scanf("%d", &x);
    
3 голосов
/ 02 ноября 2011

Это всегда хорошая практика инициализировать ваши переменные, но иногда не требуется строго . Учтите следующее:

int a;
for (a = 0; a < 10; a++) { } // a is initialized later

или

void myfunc(int& num) {
  num = 10;
}

int a;
myfunc(&a); // myfunc sets, but does not read, the value in a

или

char a;
cin >> a; // perhaps the most common example in code of where
          // initialization isn't strictly necessary

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

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

2 голосов
/ 02 ноября 2011

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

int MyVariable;
void Simplistic(int aArg){
    MyVariable=aArg;
}

//Months later:

int MyVariable;
void Simplistic(int aArg){
    MyVariable+=aArg; // Unsafe, since MyVariable was never initialized.
}

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

2 голосов
/ 02 ноября 2011

В общем случае нет необходимости инициализировать переменную с двумя заметными исключениями:

  1. Вы объявляете указатель (и не назначаете его немедленно) - вы всегда должны устанавливать их в NULL какхороший стиль и защитное программирование.
  2. Если, когда вы объявляете переменную, вы уже знаете, какое значение будет ей присвоено.Дальнейшие назначения потребляют больше циклов ЦП.

Кроме того, речь идет о приведении переменных в правильное состояние, в котором вы хотите, чтобы они выполнялись для выполняемой операции.Если вы не собираетесь читать их до того, как операция изменит их значение (и операции не важно, в каком она состоянии), нет необходимости их инициализировать.

Лично мне всегда нравитсяинициализировать их в любом случае;если вы забыли присвоить ему значение, и оно было передано в функцию по ошибке (например, оставшаяся длина буфера), то 0 обычно обрабатывается без ошибок - 32532556 не будет.

1 голос
/ 02 ноября 2011

Пока я не прочитал переменную перед записью в нее, мне не пришлось беспокоиться об ее инициализации.

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

0 голосов
/ 02 ноября 2011

Инициализация переменной, даже если она не является строго обязательной, ВСЕГДА является хорошей практикой. Несколько дополнительных символов (например, "= 0"), введенных во время разработки, могут сэкономить часы отладки позже, особенно когда забыто, что некоторые переменные остаются неинициализированными.

Попутно, я чувствую, что хорошо объявить переменную, близкую к ее использованию .

Следующее плохо:

int a;    // line 30
...
a = 0;    // line 40

Хорошо следующее:

int a = 0;  // line 40

Кроме того, если переменная должна быть перезаписана сразу после инициализации, например

int a = 0;
a = foo();

лучше написать как

int a = foo();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...