Справочная инофрмация

Неинициализированная переменная

Неинициализированная переменная (uninitialized variable)— это такая переменная, которой не было присвоено начальное значение.

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

int Sum(int n)
{
  int sum, i;
 
  for (i = 0; i < n; i++)
  {
    sum = sum + 1;
  }
 
  return sum;
}

Переменной 'sum' не присвоено начального значения, и она содержит "мусор". В отдельных случаях, при определенном везении, там может оказаться и нулевое значение. Тогда функция будет работать правильно. Но в общем случае, результат работы функции непредсказуем. Коварство подобных ошибок в том, что программа может долгое время вести себя правильно. А потом, после смены компилятора, небольшого рефакторинга и других изменений, начать выдавать ошибочные результаты. Более того, при каждом запуске программа может вести себя по-разному.

Для предотвращения подобных ошибок в языке программирования Си++ лучше инициализировать все переменные начальным значением непосредственно при объявлении. Объявлять переменные лучше всего непосредственно перед использованием, когда уже известны их начальные значения. Тогда работоспособный пример кода будет выглядеть так:

int Sum(int n)
{
  int sum = 0;
 
  for (int i = 0; i < n; i++)
  {
    sum = sum + 1;
  }
 
  return sum;
}

Использование неинициализированной памяти

Использование неинициализированной памяти — это чтение данных из буфера, который был выделен, но не заполнен начальными значениями. Такое поведение программы является ошибкой, которую иногда трудно выявить. Это так называемая "плавающая ошибкаarrow-up-right". Проявление ошибки может зависеть от версии компилятора или операционной системы, а так же от запуска "отладочной" или "релиз" версии.

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

Рассмотрим пример такой ошибки:

Ошибка заключается в неполной инициализации массива 'mainSegmenst'. Этот код будет работать корректно в 32-битной программе, где размер указателя совпадает с размером типа 'int'. И перестанет в 64-битной программе.

Указатели на функцию

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

Самым распространенным указателем на функцию является ее имя. С помощью имени функции мы можем вызывать ее и получать результат ее работы.

Но также указатель на функцию мы можем определять в виде отдельной переменной с помощью следующего синтаксиса:

Здесь тип представляет тип возвращаемого функцией значения.

имя_указателя представляет произвольно выбранный идентификатор в соответствии с правилами о наименовании переменных.

И параметры определяют тип и название параметров через запятую при их наличии.

Например, определим указатель на функцию:

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

Применим этот указатель на функцию:

Указателю на функцию можно присвоить функцию, которая соответствует указателю по возвращаемому типу и спецификации параметров:

НЕ будет аналогично следующему определению:

Во втором случае определен не указатель на функцию, а прототип функции message, которая возвращает указатель типа void*.

Рассмотрим еще один указатель на функцию:

Здесь определен указатель operation, который может указывать на функцию с двумя параметрами типа int, возвращающую также значение типа int. Соответственно мы можем присвоить указателю адреса функций add и subtract и вызвать их, передав при вызове в указатель нужные значения для параметров.

Last updated