When 0 is coerced implicitly or explicitly to a pointer type, it becomes a null pointer. That's true even on architectures where all-bits-zero is *not* a null pointer. However, in contexts where there is no expected type, as in a call to execl(), the null at the end of the args list has to be explicitly cast to (char *)0 or some other null pointer.
As for the definition of NULL, it is indeed 0 on Linux, but can also be defined as ((void *)0), as on FreeBSD and the Mac, or even as 0L on systems where ints are half-size and pointers and longs are full-size.