You're right, I was misinterpreting the language of the standard.
As a practical matter, C implementations typically define NULL as a void pointer, so the cast is not necessary in those implementations (In C++ pre C++11, NULL is always defined as a literal 0, so the cast is definitely necessary).
But it appears the standard allows C implementations to define NULL as a literal 0 or as 0L as well, so the cast is needed in portable code.
As a practical matter, C implementations typically define NULL as a void pointer, so the cast is not necessary in those implementations (In C++ pre C++11, NULL is always defined as a literal 0, so the cast is definitely necessary).
But it appears the standard allows C implementations to define NULL as a literal 0 or as 0L as well, so the cast is needed in portable code.