О "NULL" в этом конкретном коде

Я купил эту книгу под названием "Написание твердого кода".

В первой главе есть этот код:

while(*pchTo++ = *pchFrom++)
   NULL;

Я действительно не понимаю, что делает NULL в этом цикле.

Ответ 1

Автор мог бы написать полностью пустой цикл 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

Ответ 2

Этот цикл копирует строку. NULL находится здесь, чтобы обеспечить тело цикла.

Ответ 3

Вероятно, это связано с синтаксисом оператора 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 */
}

Ответ 4

Эта конструкция обеспечивает хороший способ разместить точку останова при работе с отладчиком. Некоторые IDE не позволяли мне помещать точку останова на петлю, и у меня были петли с пустыми телами. Если у вас есть оператор в вашем теле цикла, проще разместить на нем точку останова, даже если это утверждение бесполезно.

В противном случае, как уже было сказано, он должен делать то же самое, что и тело с пустым телом.