Почему возникает эта ошибка?
Обе программы содержат неопределенное поведение, поэтому ожидается, что обе они не работают.
Проблема в том, что вы разыменовывают неинициализированный указатель:
int *ip; // uninitialized, may contain any value
// ...
printf("...", *ip);
// ^^^ dereference
Это разыменование может дать вам явно случайные данные, постоянное значение или вызвать ошибку сегментации.
Что именно происходит, зависит от вашего компилятора, вашей архитектуры, ваша операционная система, флаги оптимизации и другие детали.
Какая связь между ошибкой сегментации и определением переменной?
Нет никакой связи. Определение z
заставляет вашу первую программу "казаться работающей" случайно. Как только вы измените что-то еще (например, обновите компилятор до новой версии), он может снова перестать "работать".