Я купил эту книгу под названием "Написание твердого кода".
В первой главе есть этот код:
while(*pchTo++ = *pchFrom++)
NULL;
Я действительно не понимаю, что делает NULL
в этом цикле.
Я купил эту книгу под названием "Написание твердого кода".
В первой главе есть этот код:
while(*pchTo++ = *pchFrom++)
NULL;
Я действительно не понимаю, что делает NULL
в этом цикле.
Автор мог бы написать полностью пустой цикл while
так же, как вы можете написать цикл без тегов for
. Это выглядело бы так:
while (*pchTo++ = *pchFrom++);
/* or */
while (*pchTo++ = *pchFrom++)
;
Оба из них могут казаться запутанными для некоторых людей, поэтому они добавили NULL, чтобы дать ему тело и сделать его менее запутанным.
Edit
Заметьте, что вы можете сделать то же самое с циклом for:
for (head = list->head; head->next; head = head->next);
/* or */
for (head = list->head; head->next; head = head->next)
;
/* or */
for (head = list->head; head->next; head = head->next)
NULL;
И все, что будет сделано, - это пересечь список, перейдя к следующему элементу, в то время как следующий элемент не является NULL
Этот цикл копирует строку. NULL
находится здесь, чтобы обеспечить тело цикла.
Вероятно, это связано с синтаксисом оператора null:
while condition loop
null;
end loop;
Ada использует ключевое слово null
как для константы нулевого указателя, так и для оператора null (и нескольких других вещей).
У этого есть некоторые преимущества по сравнению с оператором C null, который является точкой с запятой. В частности, он гораздо более ясен. Достаточно распространенной ошибкой в коде C является вставка случайного оператора null, добавляя точку с запятой, особенно среди неопытных программистов C, которые еще не разработали, где точки с запятой необходимы, а где нет:
while (condition);
{
/* statements */
}
Без точки с запятой операторы управляются циклом while. При этом тело цикла while пустое, и цикл, вероятно, будет бесконечным, если условие не имеет побочных эффектов.
С другой стороны, если вам действительно нужен оператор null, использование только точки с запятой может заставить читателя задаться вопросом, было ли что-то непреднамеренно опущено.
В C, null
- это макрос, который расширяется до константы нулевого указателя, определяемой реализацией. Автор использует его здесь:
while(*pchTo++ = *pchFrom++)
NULL;
как вид оператора null, который фактически работает, потому что выражение, за которым следует точка с запятой, является выражением оператора, в котором оператор оценивается по его побочным эффектам. Поскольку он не имеет побочных эффектов, он ничего не делает; он действует так же, как и действительный оператор null:
while(*pchTo++ = *pchFrom++)
;
Другая эквивалентная форма:
while(*pchTo++ = *pchFrom++)
42;
По-моему, это хорошо продуманная, но плохая идея. Это легко узнаваемо для тех немногих из нас, кто знаком с C и Ada, но большинство опытных программистов C будут смотреть на него и задаться вопросом, что там делает эта константа нулевого указателя.
Это не так плохо, как определение набора макросов, чтобы сделать C похожим на синтаксис другого языка:
#define IF if (
#define THEN )
#define BEGIN {
#define END }
#define ELSE } else {
но он в том же духе.
Мой совет: Не делай такого. Если вы хотите, чтобы ваш C-код был легко понятен читателям, знающим C, напишите идиоматический код C; не изобретать умные трюки, чтобы сделать его похожим на что-то другое. Нулевые утверждения могут вводить в заблуждение, заставляя читателя задаться вопросом, случайно ли что-то было исключено. Лучшее решение, которое, IMHO, должно использовать комментарий:
while(*pchTo++ = *pchFrom++) {
/* empty body */
}
Эта конструкция обеспечивает хороший способ разместить точку останова при работе с отладчиком. Некоторые IDE не позволяли мне помещать точку останова на петлю, и у меня были петли с пустыми телами. Если у вас есть оператор в вашем теле цикла, проще разместить на нем точку останова, даже если это утверждение бесполезно.
В противном случае, как уже было сказано, он должен делать то же самое, что и тело с пустым телом.