Почему инициализация целочисленного указателя 0 или NULL не вызывает предупреждений, хотя 0 — это целочисленная константа?
============================================================================================================================

```
int *p = 20; // warning
int *p = (int *)20;//ok
int *p = (void *)20;//тем более ок и универсальнее

int *p = 0;// ok
```
  

  

Компилятор или что-то как-то автоматически приводит 0 ? 

 0 в таком контексте — особая указательная константа для указателей в никуда, по стандартам не обязательно указывающая на нулевой адрес.  

Целочисленной константой ноль был бы в выражении  

`int *p = (int)0;` 

 Вы присваиваете значения указателю. Указатель хранит адреса. Т.е. вы записываете в переменную адрес, на который она должна указывать. Поэтому обычно присвоение какого-то целого числа указателю - это ошибка, ведь вы не можете знать что там за адреса у вас в программе нужны. Если же вы какой-то адрес откуда-то взяли, то он и был бы уже типом указателя. Отсюда и предупреждение компилятора. Довольно часто присвоения указателю целого числа - это пропущенное разыменование указателя.  

  

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

  

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

 Читайте соглашение о нулевых указателях. 

`int *p = 20; // warning`  

Тут будет записан адрес 20, по которому лежит фиг знает что. Скорее всего при попытке разыменовать такой указатель прозойдёт SEGFAULT или что-то типа того.  

`int *p = (int *)20;//ok`  

То же самое. Видимо у вас не достаточно злые опции компилятора.  

`int *p = (void *)20;//тем более ок и универсальнее`  

То же самое.  

  

`int *p = 0;// ok`  

А тут всё ок. Вроде 0 это и есть тот самый NULL