Problemas "Ponteiro do número inteiro / inteiro do ponteiro sem conversão"

Esta pergunta pretende ser uma entrada de FAQ para todas as inicializações / atribuições entre problemas de número inteiro e ponteiro.

Quero escrever código em que um ponteiro esteja definido para um endereço de memória específico, por exemplo0x12345678. Mas ao compilar esse código com o compilador gcc, recebo avisos / erros "inicialização faz ponteiro de número inteiro sem conversão":

int* p = 0x12345678;

Da mesma forma, este código fornece "a inicialização torna inteiro a partir do ponteiro sem conversão":

int* p = ...;
int i =  p;

Se eu fizer o mesmo fora da linha de declaração da variável, a mensagem é a mesma, mas diz "atribuição" em vez de "inicialização":

p = 0x12345678; // "assignment makes pointer from integer without a cast"
i = p;          // "assignment makes integer from pointer without a cast"

Testes com outros compiladores populares também fornecem mensagens de erro / aviso:

clang diz "número inteiro incompatível para conversão de ponteiro"icc diz "um valor do tipoint não pode ser usado para inicializar uma entidade do tipoint*"MSVC (cl) diz "inicializandoint* difere em níveis de indireção deint"

Pergunta: Os exemplos acima são válidos em C?

E uma pergunta de acompanhamento:

Isso não fornece avisos / erros:

int* p = 0;

Por que não?

questionAnswers(1)

yourAnswerToTheQuestion