Почему инициализация целочисленного указателя 0 или NULL не вызывает предупреждений, хотя 0 — это целочисленная константа?
0 в таком контексте — особая указательная константа для указателей в никуда, по стандартам не обязательно указывающая на нулевой адрес.
Целочисленной константой ноль был бы в выражении
int *p = (int)0;
Вы присваиваете значения указателю. Указатель хранит адреса. Т.е. вы записываете в переменную адрес, на который она должна указывать. Поэтому обычно присвоение какого-то целого числа указателю - это ошибка, ведь вы не можете знать что там за адреса у вас в программе нужны. Если же вы какой-то адрес откуда-то взяли, то он и был бы уже типом указателя. Отсюда и предупреждение компилятора. Довольно часто присвоения указателю целого числа - это пропущенное разыменование указателя.

Но 0 - исключение. Потому что нулем принято обозначать пустой, ни на что не указывающий указатель. Обычно для этого в C используют NULL, чтобы разделять число 0 и пустой указатель в коде. Но NULL, фактически и есть 0.

Компилятор ничего не приводит, а просто игнорирует присвоение 0, ибо это нормальная ситуация.