Memory allocation error in C during hashing - c

I am new to C programming and I was trying to implement typedef and hashing in my code.But I am getting compilation error when I try to allocate memory -
This is my header file
#define MAX1 11
#define MAX2 23
typedef short IP[4];
typedef enum{TRUE = 1,FALSE = 0}boolean;
typedef struct
{
IP p;
char *comp_name;
}Element;
typedef struct
{
Element e;
boolean deleted; // deleted flag
boolean empty;
}Cell;
typedef Cell secLevelHashTable[MAX2];
typedef struct secLevelHashTable *FirstLevelHashTable[MAX1];
typedef struct FirstLevelHashTable hashTable;
This my main code-
#include"hashDef.h"
#include<stdio.h>
#include<stdlib.h>
void initFirstHTable(hashTable H)
{
int i,j;
for(i=0;i<MAX1;i++)
{
H. FirstLevelHashTable[i]=(secLevelHashTable *)malloc(sizeof(secLevelHashTable));
H.FirstLevelHashTable[i]->secLevelHashTable=malloc(sizeof(Cell)*MAX2);
for(j=0;j<MAX2;j++)
{
initSecHTables(H.FirstLevelHashTable[i]->secLevelHashTable[j]);
}
}
}
void initSecHTables(Cell *ptr)
{
ptr->deleted=0;
ptr->empty=1;
}
int main()
{
hashTable h;
h=malloc(sizeof(FirstLevelHashTable));
initFirstHTable(h);
return 0;
}
This is the error I am getting-
In function ‘main’:
hashOps.c:79:13: error: storage size of ‘h’ isn’t known
hashTable h;

Fixed code below. It had numerous small issues and a big one.
Please read the related article the big one:
struct in C: Error storage size of 'params' isn't known -- this will explain "storage size unknown" error; by saying typedef struct FirstLevelHashTable hashTable; you were defining an unfinished struct, rather than referring to existing type.
Header file:
#define MAX1 11
#define MAX2 23
typedef short IP[4];
typedef enum{TRUE = 1,FALSE = 0}boolean;
typedef struct
{
IP p;
char *comp_name;
}Element;
typedef struct
{
Element e;
boolean deleted; // deleted flag
boolean empty;
}Cell;
typedef Cell secLevelHashTable[MAX2];
typedef secLevelHashTable* FirstLevelHashTable[MAX1];
typedef FirstLevelHashTable hashTable;
Main code:
#include"hashDef.h"
#include <stdio.h>
#include <stdlib.h>
void initSecHTables(Cell *ptr)
{
ptr->deleted=0;
ptr->empty=1;
}
void initFirstHTable(hashTable H)
{
int i,j;
for(i=0;i<MAX1;i++)
{
H[i]=(secLevelHashTable *)malloc(sizeof(secLevelHashTable));
for(j=0;j<MAX2;j++)
{
initSecHTables(&((*H[i])[j]));
}
}
}
int main()
{
hashTable h;
initFirstHTable(h);
return 0;
}

Related

Dereferencing pointer to incomplete type when providing function pointer

I'm getting the dereferencing pointer to incomplete type error when I try to run the following code. I've checked several other questions about this error and from what I can tell it's not due to a missing or extra struct keyword and I believe the pointer type is correct but I could be mistaken.
There might be other issues with the code as I'm just learning C, I'm happy to try and figure them out for myself I just can't seem to track down the issue with the incomplete type error.
Development/C/AI/test/src/test.c: In function ‘compare’:
Development/C/AI/test/src/test.c:10:19: error: dereferencing pointer to incomplete type ‘lrgraph_node {aka struct lrgraph_node}’
if ( strcmp(other->dataType, current->dataType == 0) ) {
test.c
#include "lrGraph.h"
#include <string.h>
int data = 1;
char *dataType = "int";
lrgraph_edge *connected[] = {};
unsigned numEdges = 0;
int compare( lrgraph_node *other, lrgraph_node *current ) {
if ( strcmp(other->dataType, current->dataType == 0) ) {
return (int)other->data - (int)current->data;
}
return -1;
}
int main() {
lrgraph_node *nodeA = lrgraph_createNode((void*)&data, dataType, &compare, connected, numEdges);
lrgraph_printVersion();
}
lrGraph.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lrGraph.h"
struct lrgraph_edge {
float weight;
lrgraph_node *nodeA;
lrgraph_node *nodeB;
};
struct lrgraph_node {
//data can be of any type
void *data;
//string to see if this node can be compared to another node based on data type
char *dataType;
int numEdges;
//comparator function which compares another node to this node
int (*compare)(lrgraph_node *other, lrgraph_node *current);
//array of connected edges
lrgraph_edge *connected[];
};
void lrgraph_printVersion() {
fprintf(stdout, "\nlrgraph version 0.01b\n");
}
lrgraph_node* lrgraph_createNode(void *data, char *dataType, int (*compare)(lrgraph_node* other, lrgraph_node* current), lrgraph_edge *connected[], unsigned numEdges) {
//allocate enough memory for the struct plus each pointer in the array of edges - https://stackoverflow.com/questions/32311269/can-we-have-a-struct-element-of-type-variable-length-array
lrgraph_node *node = malloc(sizeof(lrgraph_node) + numEdges * sizeof(lrgraph_edge));
if (NULL != node) {
node->data = data;
node->dataType = strdup(dataType);
node->compare = compare;
node->numEdges = numEdges;
//initialize each edge in the array
for( unsigned i=0; i < numEdges; i++) {
node->connected[i] = connected[i];
}
}
return node;
}
lrGraph.h
#ifndef LRGRAPH_H
#define LRGRAPH_H
typedef struct lrgraph_node lrgraph_node;
typedef struct lrgraph_edge lrgraph_edge;
lrgraph_node* lrgraph_createNode(void *data, char *dataType, int (*compare)(lrgraph_node *other, lrgraph_node *current), lrgraph_edge *connected[], unsigned numEdges);
void lrgraph_printVersion();
#endif /*LRGRAPH_H*/
"Incomplete type" means the compiler sees you're trying to use a struct type but there is no definition for that struct.
This is fine if you're only using pointers to structs (and is in fact how abstract data types are implemented in C), but if you want to dereference such a pointer, a struct definition must be visible.
In test.c only the contents of lrGraph.h are visible (i.e. typedef struct lrgraph_node lrgraph_node;), but the actual struct lrgraph_node { ... }; definition exists only in lrGraph.c.
Possible solution: Move the struct lrgraph_node { ... } definition into the header. (Alternatively, put the definition of compare into lrGraph.c).

Nested linked lists in C

I'm trying to implement a nested linked list in C, that will be used for a hierarchical menu. However, the GCC (v4.9.3-1) is complaining to nested structures, and I have no idea how to fix this. Here is the minimum (non)working example.
Is this nesting even possible in C?
main.c
#include "menu.h"
int main(void) {
Init_Menu();
return 0;
}
menu.c
#include "menu.h"
MenuItem_t LVL_0_MainMenu = {
.size = 0,
};
MenuItem_t LVL_1_Measurements = {
.size = 0,
};
void Init_Menu(void) {
Menu_Add_Child(&LVL_0_MainMenu, &LVL_1_Measurements);
}
void Menu_Add_Child(MenuItem_t *parent, MenuItem_t *child) {
parent->children[parent->size] = child;
child->parent = parent;
parent->size++;
}
menu.h
typedef struct {
unsigned char size;
MenuItem_t children[10];
MenuItem_t *parent;
} MenuItem_t;
extern MenuItem_t LVL_0_MainMenu;
extern MenuItem_t LVL_1_Measurements;
void Init_Menu(void);
void Menu_Add_Child(MenuItem_t *parent, MenuItem_t *child);
Based on answers by #bolov and #sps (once again, thanks to both of them), here is the minimum working example:
main.c
#include "menu.h"
int main(void) {
Init_Menu();
return 0;
}
menu.c
#include "menu.h"
MenuItem_t LVL_0_MainMenu = {
.size = 0,
};
MenuItem_t LVL_1_Measurements = {
.size = 0,
};
void Init_Menu(void) {
Menu_Add_Child(&LVL_0_MainMenu, &LVL_1_Measurements);
}
void Menu_Add_Child(MenuItem_t *parent, MenuItem_t *child) {
parent->children[parent->size] = child;
child->parent = parent;
parent->size++;
}
menu.h
struct MenuItem_t {
unsigned char size;
struct MenuItem_t *children[10];
struct MenuItem_t *parent;
};
typedef struct MenuItem_t MenuItem_t;
extern MenuItem_t LVL_0_MainMenu;
extern MenuItem_t LVL_1_Measurements;
void Init_Menu(void);
void Menu_Add_Child(MenuItem_t *parent, MenuItem_t *child);
The difference between this corrected program and the original (non)working program, is that the children array is defined as an array of pointers to variables of the type MenuItem_t instead of the array of variables of the same type. The other difference is that a nested list (inside the structure) should also contain the keyword struct as #bolov explained.
You need to use struct for the type used inside itself, even if you typedef it later on.
E.g. this won't work:
struct X_ {
X* next;
};
typedef struct X_ X;
But this will
struct X_ {
struct X_* next;
};
As a side note, I really don't like this form:
typedef struct {
} X;
I use:
struct X {
};
typedef struct X X;
But maybe this is just me being more fond of C++.
If you want to use that form, it's the same: you need to add struct and it works:
typedef struct {
struct X2* next;
} X2;
regarding:
struct X {
struct X arr[10];
};
You can't have that! The array is just in our way to understand why. So let's simplify:
struct X {
int a;
struct X var;
};
This can't be. What size would X be? sizeof(X) = sizeof(int) + sizeof(X) + padding. Do you see the problem? All you can do is have a pointer to X, but not an object X inside X.
Returning to your array. You need dynamic arrays:
struct X {
struct X* arr;
int arr_size;
};
It gets more complicated as you need to manage the memory (malloc/free fun), but you can't avoid it.
First of all, you cannot do,
typedef struct {
SomeName_t some_var;
} SomeName_t;
You need to do,
typedef struct somename {
struct somename some_var;
} SomeName_t;
Also, a struct cannot have a member which is an array of structure itself. However, a struct can have a member which is an array of pointer to the same structure.
struct foo {
struct foo foo_arr[10]; /* Will give error */
struct foo *foo_ptr_arr[10]; /* Legal */
};
However, I dont see a reason that your children member should be an array of struct anyways. Because, as can be seen in menu.c, you are doing
parent->children[parent->size] = child;
where the type of child is MenuItem_t *. So I think you basically wanted MenuItem_t.children to be an array of MenuItem_t *, and not an array of MenuItem_t.
So making this change should resolve your issue:
menu.h
typedef struct menuitem {
unsigned char size;
/* MenuItem_t children[10]; */ /* Not possible */
struct menuitem *children[10]; /* This is what you want to do */
struct menutem *parent;
} MenuItem_t;

Error in the use of linked-lists in C

The function doesnt work. The rest of the code is okay. It finds the maximum in the lists (its also the last element of the list) and then doesn't quit the iteration, instead of that, the program crashes. I got a hint, that suggests, that I have problems wit the us of "()". Maxhelye means the max_pos
typedef short int shorti;
typedef struct szelveny{
int szsorszam;
int lsorszam;
int het;
shorti talalat;
int tnyeremeny;
}szelveny; //szelveny-->ticket, szsorszam-->ticketnumer, //lsorszam-->lotterynumber,het-->week, tnyeremeny-->prize
typedef struct szelveny_element{
szelveny szelveny;
struct szelveny_element *next;
}szelveny_element,*szelveny_pointer;
typedef struct lottozo{
int lsorszam;
shorti het;
int sszelveny;
int nyeremeny;
} lottozo; //lottozo-->lottery
typedef struct lottozo_element{
lottozo lottozo;
struct lottozo_element *next;
} lottozo_element,*lottozo_pointer;
typedef struct het{
shorti het;
lottozo_pointer lhead;
szelveny_pointer szhead;
} het;
typedef struct het_element{
het het;
struct het_element *next;
}het_element,*het_pointer;
szelveny_pointer szelvenyek=0;
lottozo_pointer lottozok=0;
het_pointer hetek=0;
int maxnyeremenyhelye2(int ahet) //maxprizeposition, ahet-->week got as parameter
{
int max=0,maxhelye=-1;
het_pointer hp;
for(hp=hetek;hp!=0;hp=hp->next)
if(hp->het.het==ahet)
{
lottozo_pointer lp;
for(lp=hp->het.lhead;lp!=0;lp=lp->next)
{
if(lp->lottozo.nyeremeny>=max)
{
max=lp->lottozo.nyeremeny;
maxhelye=lp->lottozo.lsorszam;
}
}
return maxhelye;
}
}
Your function int maxnyeremenyhelye2(int ahet) does not always return a value - didn't your compiler warn you about this? The line
return maxhelye;
should be moved down below the following brace.

warning in pointer assigning

I'm relatively new to C. And I wrote the following code:
#include "HashTable.h"
hashTable* newHashTable()
{
hashTable* h = malloc(sizeof(hashTable));
h -> size = TABLE_SIZE;
h -> table = createTable(TABLE_SIZE);
return h;
}
entry* createTable(int size)
{
entry* table = malloc(sizeof(entry) * size);
int i;
for(i=0; i<size; i++)
(table + i) -> word = NULL;
return table;
}
and the content of HashTable.h is:
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#define TABLE_SIZE 7
#define HASH_INCREMENT 3 // for efficient utilization of the hash table keep TABLE_SIZE * 2^n relative prime to HASH_INCREMENT
typedef struct entry_t
{
char* word;
int frequency;
}entry;
typedef struct hashTable_t
{
int size;
entry* table;
}hashTable;
When I try to compile this code (with some other code too) I get the following warning:
HashTable.c: In function ‘newHashTable’:
HashTable.c:7:13: warning: assignment makes pointer from integer without a cast [enabled by default]
Line 7 is actually the third line in newHashTable() function. I was looking at this for hours now. Please help me to resolve this warning.
Ansii C assumes that any function that is called without having been declared returns int.
You should either declare createTable before newHashTable
entry* createTable(int size);
hashTable* newHashTable()
{
/* implementation */
}
entry* createTable(int size)
{
/* implementation */
}
or move its implementation before any calls
entry* createTable(int size)
{
/* implementation */
}
hashTable* newHashTable()
{
/* implementation */
}
or declare the functions in the header that also defines the struct
typedef struct entry_t
{
char* word;
int frequency;
}entry;
typedef struct hashTable_t
{
int size;
entry* table;
}hashTable;
entry* createTable(int size);
hashTable* newHashTable();

error: invalid type argument of '->' (have 'struct node')

Why cant i access the pointer "Cells" like an array ? i have allocated the appropriate memory why wont it act like an array here? it works like an array for a pointer of basic data types.
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#define MAX 10
struct node
{
int e;
struct node *next;
};
typedef struct node *List;
typedef struct node *Position;
struct Hashtable
{
int Tablesize;
List Cells;
};
typedef struct Hashtable *HashT;
HashT Initialize(int SIZE,HashT H)
{
int i;
H=(HashT)malloc(sizeof(struct Hashtable));
if(H!=NULL)
{
H->Tablesize=SIZE;
printf("\n\t%d",H->Tablesize);
H->Cells=(List)malloc(sizeof(struct node)* H->Tablesize);
should it not act like an array from here on?
if(H->Cells!=NULL)
{
for(i=0;i<H->Tablesize;i++)
the following lines are the ones that throw the error
{ H->Cells[i]->next=NULL;
H->Cells[i]->e=i;
printf("\n %d",H->Cells[i]->e);
}
}
}
else printf("\nError!Out of Space");
}
int main()
{
HashT H;
H=Initialize(10,H);
return 0;
}
The error I get is as in the title-error: invalid type argument of '->' (have 'struct node').
A correct version of your code is given below. It is always advisable not to use pointers while using typedef.
The only problem with your code apart from that was your access method.
H->cells[i]->next will throw an error.
Also H->cells->[i]e was invalid syntax.
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#define MAX 10
struct node
{
int e;
struct node *next;
};
typedef struct node List;
typedef struct node Position;
struct Hashtable
{
int Tablesize;
List *Cells;
};
typedef struct Hashtable HashT;
HashT Initialize(int SIZE,HashT *H)
{
int i;
H=(HashT*)malloc(sizeof(struct Hashtable));
if(H!=NULL)
{
H->Tablesize=SIZE;
printf("\n\t%d",H->Tablesize);
H->Cells=(List*)malloc(sizeof(List)*H->Tablesize);
//should it not act like an array from here on?
if(H->Cells!=NULL)
{
for(i=0;i<H->Tablesize;i++)
//the following lines are the ones that throw the error
{
H->Cells[i].next=NULL;
H->Cells[i].e=i;
printf("\n %d",H->Cells[i].e);
}
}
}
else printf("\nError!Out of Space");
return *H;
}
int main()
{
HashT H;
H=Initialize(10,&H); //return is not required as already we are passing by address
return 0;
}
The
H->Cells[i]->next
should be
H->Cells[i].next
(Similarly for e.)
This is a version of your program without the typedefs. Which one is more readable?
#include <stdio.h>
#include <stdlib.h>
struct node {
struct node *next;
int e;
};
struct Hashtable {
unsigned Tablesize;
struct node *Cells;
};
struct Hashtable *Initialize(unsigned size)
{
unsigned iii;
struct Hashtable *hp;
hp = malloc (sizeof *hp);
if(!hp) {
fprintf(stderr, "Error!Out of Space\n");
return NULL;
}
hp->Cells = malloc(size * sizeof *hp->Cells );
if(!hp->Cells) {
hp->Tablesize = 0;
return hp;
}
hp->Tablesize = size;
fprintf(stderr, "\t%u\n", hp->Tablesize);
for(iii=0; iii < hp->Tablesize; iii++) {
hp->Cells[iii].next = NULL;
hp->Cells[iii].e = iii;
fprintf( stderr, " %u\n", hp->Cells[iii].e);
}
return hp;
}
int main()
{
struct Hashtable *hashtab;
hashtab = Initialize(10);
return 0;
}
The changes:
removed the typedefs; since they are confusing
removed the casts from malloc() not needed and potentially dangerous.
changed the sizes to unsigned. A size can never be negative
diagnostic output should go to stderr.
a few of levels of indentation can be avoided by doing the error-case first, and returning early from the function on error.

Resources