char* str;
объявляет указатель на символ, но не оставляет места для самих символов. Кроме того, поскольку вы не инициализировали его, он указывает на какое-то случайное место в памяти.
Затем fgets(str, 80, fp)
говорит, что нужно взять 80 символов из файла и сохранить их, начиная с указанного места. Поскольку (скорее всего) вашей программе не принадлежит это местоположение, вы получаете ошибку по умолчанию.
char str[100];
резервирует место для 100 символов в стеке в виде массива, и вы можете использовать str
в качестве указателя на начало этого массива. Ваша программа может делать с этой памятью все, что захочет, поэтому при выполнении команды fgets
не возникает никаких ошибок. Обратите внимание, что если ваш массив слишком короткий, то у вас все еще могут быть проблемы, хотя они не обязательно являются ошибками сегмента.