I bought this book called "Writing Solid Code".
In the first chapter, there's this code:
while(*pchTo++ = *pchFrom++)
NULL;
I really don't get what that NULL
does in that loop.
I bought this book called "Writing Solid Code".
In the first chapter, there's this code:
while(*pchTo++ = *pchFrom++)
NULL;
I really don't get what that NULL
does in that loop.
The author could have written an entirely empty while
loop just like you can write a body-less for
loop. That would have looked like:
while (*pchTo++ = *pchFrom++);
/* or */
while (*pchTo++ = *pchFrom++)
;
Both of which might look confusing for some people so they added the NULL to give it a body and make it less confusing.
Edit
Note you can do the same with a for loop:
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;
And all that will do is traverse a list by going to the next element while the next element is not NULL
That loop copies a string. The NULL
is just there to provide a loop body.
It's likely inspired by the syntax of Ada's null statement:
while condition loop
null;
end loop;
Ada uses the null
keyword both for the null pointer constant and for the null statement (and a few other things).
It does have some advantages over C's null statement, which is just a semicolon. In particular, it's much more explicit. A fairly common error in C code is to insert an accidental null statement by adding a semicolon, particularly among inexperienced C programmers who haven't yet worked out where semicolons are necessary and where they aren't:
while (condition);
{
/* statements */
}
Without the semicolon, the statements are controlled by the while loop. With it, the body of the while loop is empty, and the loop is likely be infinite if the condition has no side effects.
On the other hand, if you really want a null statement, using just a semicolon can leave the reader wondering if something was unintentionally left out.
In C, NULL
is a macro that expands to an implementation-defined null pointer constant. The author is using it here:
while(*pchTo++ = *pchFrom++)
NULL;
as a kind of null statement -- which actually works, because an expression followed by a semicolon is a statement expression in which the statement is evaluated for its side effects. Since it has no side effects, it does nothing; it acts just like a real null statement:
while(*pchTo++ = *pchFrom++)
;
Another equivalent form:
while(*pchTo++ = *pchFrom++)
42;
In my opinion, this is well intended but a bad idea. It's easily recognizable to those few of us who happen to be familiar with both C and Ada, but most experienced C programmers will look at it and wonder what the heck that null pointer constant is doing there.
It's not quite as bad as defining a set of macros to make C look like another language's syntax:
#define IF if (
#define THEN )
#define BEGIN {
#define END }
#define ELSE } else {
but it's in the same spirit.
My advice: Don't do this kind of thing. If you want your C code to be easily understandable by readers who know C, write idiomatic C code; don't invent clever tricks to make it look like something else. Null statements can be confusing, leading the reader to wonder if something was left out accidentally. The best solution that, IMHO, is to use a comment:
while(*pchTo++ = *pchFrom++) {
/* empty body */
}
This construct provides a good way to place a breakpoint when working with a debugger. Some IDEs did not let me place a breakpoint on a loop and I had loops with empty bodies. If you have a statement in your loop body, it is easier to place a breakpoint on it, even if that statement is useless.
Otherwise, as it has already been said, it should do exactly the same thing than a body with an an empty body.