Ну, это зависит. Если вы посмотрите на таблицу [i], как вы узнаете, пуста она или нет? Если вы используете list **, тогда table [i] будет type list *, и поэтому вы можете легко определить, является ли он пустым, если он нулевой. Если вы используете тип list *, то таблица [i] является списком, и поэтому, если вы не используете нулевое, пустое или какое-либо другое значение для ключа в качестве значения стража, указывающего, что список пуст, он не будет работать. Так что, да, вы можете использовать список *, но тогда вам нужно добавить дополнительное условие стража, которое также может ограничивать типы ключей, которые вы разрешаете. В качестве альтернативы, вы можете просто проигнорировать первый элемент списка [i], однако это будет расточительно. Я также должен отметить, что использование list * вместо list ** затрудняет вставку элемента в начало таблицы [i]; если вы используете тип списка **, то вам просто нужно установить следующий указатель новой записи на текущее значение таблицы [i], а затем присвоить таблице [i] адрес новой выделенной записи. Если вы используете тип list *, вам нужно вставить элемент между таблицей [i] и таблицей [i] -> next, что делает логику для вставки излишне сложной.
Кроме того, я должен добавить, что определение вашей хеш-таблицы неверно. Хеш-таблица должна отображать один набор элементов в другой. Ваша структура списка имеет одно значение. Ему нужен и ключ, и значение. Лучшим объявлением для хеш-таблицы будет следующее:
typedef struct HashTableEntry
{
char* key;
void* value;
struct HashTableEntry* next;
} HashTableEntry;
typedef struct HashTable
{
HashTableEntry** entries;
int capacity; // size of entries
int length; // number of key/value pairs currently in map
} HashTable;