Рубрики

Пустой указатель на C

На очень высоком уровне мы можем думать о NULL как о нулевом указателе, который используется в C для различных целей. Некоторые из наиболее распространенных случаев использования NULL:
а) Инициализировать переменную-указатель, когда этой переменной-указателю еще не назначен какой-либо действительный адрес памяти.
б) Проверить нулевой указатель перед доступом к любой переменной указателя. Таким образом, мы можем выполнять обработку ошибок в коде, связанном с указателем, например, переменная разыменования указателя, только если она не равна NULL.
в) передать нулевой указатель на аргумент функции, когда мы не хотим передавать действительный адрес памяти.

Примером является

int * pInt = NULL;

Пример б

if(pInt != NULL) / * Мы также можем использовать if (pInt) * /

{ / * Какой-то код * /}

else

{ / * Какой-то код * /}

Пример с

int fun(int *ptr)

{

 / * Забавные вещи сделаны здесь с помощью ptr * /

 return 10;

}
fun(NULL);

Следует отметить, что указатель NULL отличается от неинициализированного и висящего указателя. В определенном контексте программы все неинициализированные или висячие или NULL-указатели недопустимы, но NULL — это конкретный недопустимый указатель, упомянутый в стандарте C и имеющий конкретные цели. Мы имеем в виду, что неинициализированные и висячие указатели недействительны, но они могут указывать на некоторый адрес памяти, который может быть доступен через доступ к памяти непреднамеренно.

#include <stdio.h>

int main()

{

 int *i, *j;

 int *ii = NULL, *jj = NULL;

 if(i == j)

 {

  printf("This might get printed if both i and j are same by chance.");

 }

 if(ii == jj)

 {

  printf("This is always printed coz ii and jj are same.");

 }

 return 0;

}

Конкретно упоминая указатель NULL, стандарт C предоставляет механизм, с помощью которого программист C может использовать и проверять, является ли данный указатель легитимным или нет. Но что именно NULL и как оно определяется? Строго говоря, NULL расширяется до определенной в реализации постоянной нулевого указателя, которая определяется во многих заголовочных файлах, таких как « stdio.h », « stddef.h », « stdlib.h » и т. Д. Давайте посмотрим, что стандарты C говорят о нулевом указатель. Из стандартного пункта C11 6.3.2.3,

« Выражение из целочисленной константы со значением 0 или такое выражение, приведенное к типу void *, называется константой нулевого указателя. Если константа нулевого указателя преобразуется в тип указателя, результирующий указатель, называемый нулевым указателем, гарантированно сравнивается с неравным указателем на любой объект или функцию. »

Прежде чем мы продолжим обсуждение NULL :), давайте упомянем несколько строк о стандарте C на тот случай, если вы захотите обратиться к нему для дальнейшего изучения. Обратите внимание, что ISO / IEC 9899: 2011 является последним стандартом языка C, который был опубликован в декабре 2011 года. Он также называется стандартом C11. Для полноты отметим, что предыдущими стандартами для C были C99, C90 (также известный как ISO C) и C89 (также известный как ANSI C). Хотя настоящий стандарт C11 можно приобрести в ISO, есть проект документа, который доступен в свободном доступе бесплатно.

Возвращаясь к нашему обсуждению, макрос NULL определяется как ((void *) 0) в заголовочных файлах большинства реализаций компилятора Си. Но стандарт C говорит, что 0 также является константой нулевого указателя. Это означает, что следующее также совершенно законно согласно стандарту.

int * ptr = 0;

Обратите внимание, что 0 в приведенном выше операторе C используется в указателе-контексте и отличается от 0 как целое число. Это одна из причин, по которой использование NULL является предпочтительным, поскольку в коде четко указывается, что программист использует нулевой указатель, а не целое число 0. Другая важная концепция NULL заключается в том, что « NULL расширяется до определенной в реализации постоянной нулевого указателя » , Это утверждение также из C11 пункта 7.19. Это означает, что внутреннее представление нулевого указателя может быть ненулевым битовым шаблоном для передачи нулевого указателя. Вот почему NULL не всегда должен быть представлен внутри как битовый шаблон со всеми нулями. Реализация компилятора может выбрать представление «константы нулевого указателя» в виде битового шаблона для всех 1 или чего-либо еще. Но опять же, как программисту на Си, нам не нужно сильно беспокоиться о внутреннем значении нулевого указателя, если мы не вовлечены в кодирование компилятора или даже ниже уровня кодирования. Сказав это, обычно NULL представляется как все биты, установленные только в 0. Чтобы узнать это на конкретной платформе, можно использовать следующее

#include<stdio.h>

int main()

{

 printf("%d",NULL);

 return 0;

}

Скорее всего, это печать 0, которая является типичным значением внутреннего нулевого указателя, но, опять же, оно может варьироваться в зависимости от компилятора / платформы C. Вы можете попробовать несколько других вещей в вышеуказанной программе, таких как printf («% c», NULL) или printf («% s», NULL) и даже printf («% f», NULL) . Их результаты будут различаться в зависимости от используемой платформы, но было бы интересно, особенно использование % f с NULL!

Можем ли мы использовать оператор sizeof () для NULL в C? Что ж, использование sizeof (NULL) разрешено, но точный размер зависит от платформы.

#include<stdio.h>

int main()

{

 printf("%lu",sizeof(NULL));

 return 0;

}

Поскольку NULL определяется как ((void *) 0) , мы можем думать о NULL как о специальном указателе, и его размер будет равен любому указателю. Если размер указателя платформы составляет 4 байта, выходные данные вышеприведенной программы будут равны 4. Но если размер указателя на платформе составляет 8 байтов, выходные данные вышеуказанной программы будут равны 8.

Как насчет разыменования NULL? Что произойдет, если мы будем использовать следующий код C

#include<stdio.h>

int main()

{

 int * ptr = NULL;

 printf("%d",*ptr);

 return 0;

}

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

Поскольку NULL обычно определяется как ((void *) 0) , давайте немного поговорим о типе void . Согласно стандартному пункту 6.2.5 C11, « тип void содержит пустой набор значений; это неполный тип объекта, который не может быть завершен ». Даже в пункте 6.5.3.4 пункта C11 упоминается, что « оператор sizeof не должен применяться к выражению, имеющему тип функции или неполный тип, к имени в скобках такого типа или к выражению, которое обозначает элемент битового поля. По сути, это означает, что void является неполным типом, размер которого не имеет никакого смысла в программах на C, но реализации (такие как gcc) могут выбрать sizeof (void) равным 1, чтобы плоская память, указанная указателем void, могла рассматриваться как нетипизированная память, т.е. последовательность байтов. Но вывод следующего не должен быть одинаковым на всех платформах.

#include<stdio.h>

int main()

{

 printf("%lu",sizeof(void));

 return 0;

}

На gcc вышеприведенный вывод будет 1. А как насчет sizeof (void *) ? Здесь C11 упомянул руководящие принципы. Из пункта 6.2.5 « Указатель на void должен иметь те же требования к представлению и выравниванию, что и указатель на тип символа ». Вот почему вывод следующего будет таким же, как любой размер указателя на машине.

#include<stdio.h>

int main()

{

 printf("%lu",sizeof(void *));

 return 0;

}

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

1. Всегда инициализируйте переменные-указатели как NULL.
2. Всегда выполняйте проверку NULL перед обращением к любому указателю.

Пожалуйста, сделайте Like / Tweet / G + 1, если вы найдете вышеупомянутое полезным. Кроме того, пожалуйста, оставьте нас, чтобы комментировать для дальнейшего разъяснения или информации. Мы будем рады помочь и научиться 🙂

Рекомендуемые посты:

Пустой указатель на C

0.00 (0%) 0 votes