i
обычно является именем целочисленного (обычно int
) объекта.Вызов указателя i
сбивает с толку.
Итак, давайте предположим, что у вас есть
int *p;
Вы говорите "его память выделена".Вы имеете в виду память для самого объекта-указателя (которая выделяется при объявлении p
), или вы имеете в виду память для int
объекта, на который он указывает?
В любом случае вы не можетескажите, была ли она инициализирована или нет.
Если p
имеет статическую продолжительность хранения, то его начальное значение (при отсутствии явного инициализатора) является нулевым указателем;это ни на что не указывает.В противном случае его начальное значение является мусором, и вы не можете безопасно сделать с ним что-либо , кроме как присвоить ему какое-либо действительное значение.
Если, с другой стороны, вы имеете в виду, что p
был инициализирован, чтобы указывать на некоторый int
объект, но этот объект мог или не мог быть инициализирован, тогда у вас есть похожая проблема.Если у вас есть:
int *p;
p = malloc(sizeof *p);
if (p == NULL) {
/* malloc() failed! */
exit(EXIT_FAILURE);
}
, то p
указывает на выделенный объект int
, но значение этого объекта является мусором.В большинстве систем вы можете безопасно получить доступ к значению (*p
) - но в этом нет никакого смысла.Но возможно, что int
имеет представлений ловушек ;в этом случае простое обращение к значению *p
ведет к неопределенному поведению и может привести к сбою вашей программы.А оптимизирующий компилятор может делать неожиданные вещи в присутствии неопределенных объектов; может предположить , что оно было инициализировано для некоторого значения, и не беспокоиться о фактическом извлечении сохраненного значения.
Не существует специального значения, маркера или флага для неинициализированного int
объекта,Вы, программист, должны убедиться, что у любого объекта есть действительное значение, прежде чем пытаться получить к нему доступ.(Некоторые языки отслеживают эти вещи для вас; C не является одним из этих языков. Конечно, многие реализации этих языков написаны (очень тщательно) на C.)
Итак, вызадавая неправильный вопрос.Если вы не знаете, был ли объект инициализирован, решение состоит в том, чтобы выяснить (логически, когда вы пишете код, а не во время выполнения программы), был ли он инициализирован.Лучший способ сделать это обычно состоит в том, чтобы был инициализирован .
Если вы пытаетесь сделать что-то вроде следующего псевдокода:
if (/* *p has been initialized */) {
do something with *p;
}
else {
do something else;
}
тогда вы делаете это неправильно.Вместо:
/* Ensure p points to a valid int object */
*p = some_value;
/* Now you *know* *p has been initialized */
do something with *p;