Начальное значение calloc, при использовании со структурой - PullRequest
0 голосов
/ 16 декабря 2018

Я пытаюсь написать очень простую хеш-таблицу, используя следующий код:

#include <stdio.h>
#include <string.h>
#define SIZE 10

typedef struct {
    char *first_name;
    char *last_name;
} Employee;

typedef struct {
    Employee *table;
} Hashtable;

void initHashtable(Hashtable *ht) {
    ht->table = (Employee *)calloc(SIZE, sizeof(Employee));
}

int hashKey(char *key) {
    int length = strlen(key);
    return length % SIZE;
}

void put(Hashtable *ht, Employee emp, char *key) {
    int hashedKey = hashKey(key);
    ht->table[hashedKey] = emp;
}

И я могу вставить элементы, выполнив:

int main(int argc, char const *argv[]) {

    Employee e1;
    e1.first_name = "John";
    e1.last_name = "Doe";

    Hashtable ht;

    initHashtable(&ht);
    put(&ht, e1, "Doe");

    return 0;
}

Но я хочу изменитьФункция "положить", поэтому, когда я пытаюсь что-то вставить, он проверит, пустой ли этот индекс или нет.Если пусто, вернуть какое-то сообщение, если нет, то вставить в этот индекс.Похоже на:

void put(Hashtable *ht, Employee emp, char *key) {
    int hashedKey = hashKey(key);

    if (ht->table[hashedKey] != 0) {
        printf("Employee is in that index!\n");
    } else {
        ht->table[hashedKey] = emp;
    }
}

Но это «если утверждение» не работает.Итак, я попытался с 0 и NULL.Затем я попробовал с приведением типа:

if(ht->table[hashedKey] != (Employee *)0)

и

if(ht->table[hashedKey] != (Employee)0)

Ничего не работает.Мой вопрос, я знал, что Calloc инициализируется с 0, ноль.Тогда в случае структуры, с чем инициализируется calloc?

Ответы [ 2 ]

0 голосов
/ 16 декабря 2018

Но это «если утверждение» не работает.

Под «не работает» я полагаю, вы имеете в виду «не компилируется».

Итак, я попытался с 0 и NULL.Затем я попробовал с приведением типа:

if(ht->table[hashedKey] != (Employee *)0)

и

if(ht->table[hashedKey] != (Employee)0)

Ничего не работает.

Ваш компилятор будет выдавать диагностические сообщения, объясняющие почему он отклоняет ваш код.Такая диагностика иногда может быть загадочной, но, несомненно, жалобы на тип данных должны заставить вас задать себе вопрос «какие типы здесь задействованы?».Тем не менее, мы можем помочь:

  • ht->table[hashedKey] имеет тип Employee (структура, а не указатель на нее).Вероятно, это наиболее важный для ваших целей, но давайте продолжим ....

  • 0 - это константа типа int, которая также служит нулевым указателемконстанта (независимо от ее типа).

  • (Employee *) 0 - нулевой указатель типа Employee *.

  • (Employee) 0 - недопустимыйвыражение.У него нет типа, поскольку недопустимо приводить int к типу структуры, например Employee.

Типы структуры, такие как Employee, не являются допустимыми операндамиоператор != (или оператора ==, или большинства других).Это твоя главная проблема.Даже если вы создали представление Employee со всеми нулевыми битами, что можно сделать различными способами, вы все же не смогли бы напрямую сравнить его на (in) равенство с ht->table[hashedKey] через любой из операторов Си.Однако даже если бы структуры были сопоставимыми, не имеет смысла сравнивать структуру с указателем любого типа, как это пытается сделать ваш первый пример.

Мой вопросЯ знал, что Calloc инициализируется с 0, ноль.Затем, в случае структуры, с которой инициализируется calloc?

Это, похоже, не имеет никакого отношения к вашей проблеме, но поскольку вы спросили, calloc инициализирует пространство, которое оно выделяет всем нулевым битам,Для целочисленных типов (в том числе среди членов структуры) это представление равно 0. Для других типов, включая типы указателей, язык не определяет, что означает это представление.

Чтобы проверить, являются ли две структурыравно, вам нужно сравнить их член за членом.Однако в вашем конкретном случае вам не нужно сравнивать структуры, вам просто нужно проверить элементы структуры one .Однако, поскольку значение указателя со всеми битами, равными нулю, не обязательно является нулевым указателем, но, тем не менее, вполне может не указывать ни на что, небезопасно сравнивать значение указателя, выделенное через calloc с что-либо .Учитывая это, и ваша структура Employee не имеет никаких не указательных членов, инициализация памяти calloc не принесет вам ничего полезного.

Вместо этого вам следует вручную инициализировать каждый элемент хеш-таблицы:

void initHashtable(Hashtable *ht) {
    ht->table = malloc(SIZE, sizeof(Employee));
    for (int i = 0; i < SIZE; i++) {
        ht->table[i].first_name = NULL;
        ht->table[i].last_name = NULL;
    }
}

Сделав это, вы можете проверить, был ли назначен данный слот в таблице, проверив членов:

if (ht->table[hashedKey].first_name != NULL || ht->table[hashedKey].last_name != NULL) // ...

Поскольку нулевые указатели оцениваются как ложные в логическом контекстеи ненулевые указатели (даже недействительные) оцениваются как true, вы можете сократить его как

if (ht->table[hashedKey].first_name || ht->table[hashedKey].last_name) // ...

... если хотите.Любая версия сообщает вам, что элемент таблицы был назначен.

0 голосов
/ 16 декабря 2018

Мой вопрос: я знал, что calloc инициализируется с 0, ноль.Тогда в случае структуры, с которой инициализируется calloc?

calloc не имеет абсолютно никакого представления о том, как вы будете использовать память.Он просто дает вам запрошенную сумму со всеми битами, установленными на ноль.Посмотрите на его прототип:

void * calloc(size_t num, size_t size)

Параметры num и size - это информация only , которую имеет calloc.

...