The author is right that preprocessor macros are not typed (in contrary to e.g. variables, where typing is enforced during their declaration). So macros are more dangerous in this regard, as compiler is unable to verify type correctness in expressions and you may miss an important warning/error message during compilation
Of course compiler creators can (and usually do, I hope) provide a version of NULL macro that expands to a value with a cast, equivalent (not identical!) to the C definition:
#define N ((void*)0)
BTW: since C++11 NULL can evaluate to std::nullptr_t type.
So I would not expect too much problems with NULL, but you may consider avoiding using your own macros. Or at least use your macros with caution as long as you are not perfectly sure that you can foresee the many contexts in which your macro may happen to be expanded in various expressions.
For a short exercise, you can try the below, to see that macros have no type, so their type gets deduced in the expressions, subject to e.g. arithmetic conversions or promotions. In the below example, MY_NULL macros (=without casting) result in quite dangerous assignments. That is what your book author has in mind and tries to warn you.
MY_TYPED macros evaluate to casted expressions, which ensures that compilers catches error when trying e.g. i = MY_TYPED_NULL;
#define MY_NULL 0
#define MY_TYPED_NULL ((void*)0)
int i;
float f;
void* v;
i = MY_NULL; // bad: no compiler error
f = MY_NULL; // bad: no compiler error
v = MY_NULL; // seems to match programmer's intention
i = MY_TYPED_NULL; // good: compiler error
f = MY_TYPED_NULL; // good: compiler error
v = MY_TYPED_NULL; // correct