Reputation: 473
I am trying to write a very simple hash table by using following code:
#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;
}
And I can insert elements by doing:
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;
}
But I want to modify the "put" function, so when I try to insert something, it will check if that index is empty or not. If empty then return some message, if not then insert on that index. Similar to:
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;
}
}
But this "if statement" is not working. So, i tried with both 0 and NULL. Then I tried with casting like:
if(ht->table[hashedKey] != (Employee *)0)
and
if(ht->table[hashedKey] != (Employee)0)
Nothing is working. My question is I knew calloc initializes with 0, zero. Then in case of struct what do calloc initializes with?
Upvotes: 0
Views: 1669
Reputation: 181008
But this "if statement" is not working.
By "not working", I presume you mean "does not compile".
So, i tried with both 0 and NULL. Then I tried with casting like:
if(ht->table[hashedKey] != (Employee *)0)
and
if(ht->table[hashedKey] != (Employee)0)
Nothing is working.
Your compiler will be emitting diagnostic messages explaining why it rejects your code. Such diagnostics can sometimes be cryptic, but surely the complaints about datatype should lead you to ask yourself the question "what are the types involved here?". Nevertheless, we can help:
ht->table[hashedKey]
has type Employee
(a structure, not a pointer to one). This is probably the most important one for your purposes, but let's go on ....
0
is a constant of type int
, which also serves as a null pointer constant (its type notwithstanding).
(Employee *) 0
is a null pointer of type Employee *
.
(Employee) 0
is an invalid expression. It has no type, because it is not valid to cast an int
to a structure type such as Employee
.
Structure types such as Employee
are not valid operands of the !=
operator (or of the ==
operator, or of most others). This is your main problem. Even if you produced an Employee
representation with all bits zero, which can be done in various ways, you still could not directly compare it for (in)equality with ht->table[hashedKey]
via any of C's operators. Even if structures were comparable, however, it would not make sense to compare a structure with a pointer of any type, as your first example tries to do.
My question is I knew calloc initializes with 0, zero. Then in case of struct what do calloc initializes with?
This does not appear to have anything to do with your problem, but since you asked, calloc
initializes the space it allocates to all bits zero. For integer types (including among the members of a structure), this is a representation of 0. For other types, including pointer types, the language does not specify what this representation signifies.
To check whether two structures are equal, you need to compare them member by member. In your particular case, however, you don't really need to compare structures, you just need to check the members of one structure. However, because a pointer value with all bits zero is not necessarily a null pointer, yet may well not point to anything, it is not safe to compare a pointer value allocated via calloc
to anything. With that being the case, and your Employee
structure not having any non-pointer members, calloc
's memory initialization does not gain you anything useful.
Instead, you should manually initialize each hash table element:
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;
}
}
Having done that, you can check whether a given slot in the table has been assigned by checking the members:
if (ht->table[hashedKey].first_name != NULL || ht->table[hashedKey].last_name != NULL) // ...
Because null pointers evaluate to false in boolean context and non-null pointers (even invalid ones) evaluate to true, you can abbreviate that as
if (ht->table[hashedKey].first_name || ht->table[hashedKey].last_name) // ...
... if you prefer. Either version tells you that the table element has been assigned.
Upvotes: 3
Reputation: 31409
My question is I knew calloc initializes with 0, zero. Then in case of struct what do calloc initializes with?
calloc
has absolutely no idea how you will use the memory. It just gives you the amount you requested with all bits set to zero. Look at the prototype for it:
void * calloc(size_t num, size_t size)
The parameters num
and size
is the only information that calloc
has.
Upvotes: 5