Вот, что говорит стандарт:
5.2.5 p.3
If E1 has the type “pointer to class X,” then the expression E1->E2 is converted to the equivalent form (*(E1)).E2;
То есть p->f() эквивалентно (*p).f(). Имеем разыменование нулевого указателя, что приводит к неопределенному поведению
1.9 p.4
Certain other operations are described in this International Standard as undefined (for example, the effect of dereferencing the null pointer).
На практике при вызове функции-члена через указатель, адрес хранящийся в указателе помещается в регистр (ECX для MSVC) или в стек (GCC, Borland). В данном случае туда помещается NULL, так как обращений к данным членам в функции f() нет, то это и не приводит к проблемам, потому что реально обращение к указателю не происходит.