Программирование >>  Перегруженные имена функций и идентификаторы 

1 ... 174 175 176 [ 177 ] 178 179 180 ... 210


Пусть NULL был определен следующим образом: #define NULL ((char *)0). Означает ли это, что функциям можно передавать NULL без преобразования типа?

В общем, нет. Проблема в том, что существуют компьютеры, которые используют различные внутренние представления для указателей на различные типы данных. Предложенное определение через #define годится, когда функция ожидает в качестве передаваемого параметра указатель на char, но могут возникнуть проблемы при передаче указателей на переменные других типов, а верная конструкция:

FILE *fp = NULL; может не сработать.

Тем не менее, ANSI C допускает другое определение для NULL:

#define NULL ((void *)0)

Кроме помощи в работе некорректным программам (но только в случае машин, где указатели на разные типы имеют одинаковые размеры, так что помощь здесь сомнительна) это определение может выявить программы, которые неверно используют NULL (например, когда был необходим символ ASCII NUL).

Я использую макрос #define Nullptr(type) (type *)0, который помогает задавать тип нулевого указателя

Хотя этот трюк и популярен в определенных кругах, он

стоит немного. Он не нужен при сравнении и присваивании. Он

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

читает программу, что автор здорово сечет в нулевых

указателях, и требует гораздо более аккуратной проверки

определения макроса, его использования и всех остальных

случаев применения указателей.

Корректно ли использовать сокращенный условный оператор if(p) для проверки того, что указатель ненулевой? А что если внутреннее представление для нулевых указателей отлично от нуля?

Когда Си требует логическое значение выражения (в инструкциях if, while, for и do и дя операторов &&, , ! и ?) значение false получается, когда выражение равно нулю, а значение true получается в противоположном случае. Таким образом, если написано:

if(expr)



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

if(expr != 0)

Подставляя тривиальное выражение, содержащее указатель p вместо expr , получим:

if(p)

эквивалентно

if(p != 0)

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

Оператор логического отрицания ! может быть описан так:

!expr

на самом деле эквивалентно

expr?0:1

Читателю предлагается в качестве упражнения показать, что

if(!p)

эквивалентно

if(p == 0)

Хотя сокращения типа if(p) совершенно корректны, кое-кто считает их использование дурным стилем.

Если NULL и 0 эквивалентны, то какую форму из двух использовать?

Многие программисты верят, что NULL должен использоваться во всех выражениях, содержащих указатели как напоминание о том, что значение должно рассматриваться как указатель. Другие же чувствуют, что путаница, окружающая NULL и 0 , только усугубляется, если 0 спрятать в операторе #define и предпочитают использовать 0 вместо NULL . Единственного ответа не существует. Программисты на Си должны понимать, что NULL и 0 взаимозаменяемы и что 0 без преобразования типа можно без сомнения использовать при инициализации, присваивании и сравнении. Любое использование NULL (в противоположность 0 ) должно рассматриваться как ненавязчивое напоминание, что



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

Даже если это и будет работать, с точки зрения стиля программирования это плохо.(ANSI позволяет определить NULL с помощью #define как (void *)0. Такое определение не позволит использовать NULL там, где не подразумеваются указатели). Особенно не рекомендуется использовать NULL там, где требуется нулевой код ASCII (NUL). Если необходимо, напишите собственное определение:

#define NUL \0

Но не лучше ли будет использовать NULL (вместо 0) в случае, когда значение NULL изменяется, быть может, на компьютере с ненулевым внутренним представлением нулевых указателей?

Нет. Хотя символические константы часто используются вместо чисел из-за того, что числа могут измениться, в данном случае причина, по которой используется NULL, иная. Еще раз повторим: язык гарантирует, что 0, встреченный там, где по контексту подразумевается указатель, будет заменен компилятором на нулевой указатель. NULL используется только с точки зрения лучшего стиля программирования.

Я в растерянности. Гарантируется, что NULL равен 0, а нулевой указатель нет?

Термин null или NULL может не совсем обдуманно использоваться в нескольких смыслах:

1. Нулевой указатель как абстрактное понятие языка.

2. Внутреннее (на стадии выполнения) представление нулевого указателя, которое может быть отлично от нуля и различаться для различных типов указателей. О внутреннем представлении нулевого указателя должны заботиться только создатели компилятора. Программистам на Си это представление не известно.

3. Синтаксическое соглашение для нулевых указателей, символ 0 .

4. Макрос NULL который с помощью #define определен как 0 или (void *)0 .



1 ... 174 175 176 [ 177 ] 178 179 180 ... 210

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика