How to initialize an void* pointer from struct - c

I have a struct Element. When I try to initialize the elements array to NULL,
I get the error: incompatible types when assigning to type Element from type void *.
How to initialize the void * array?
typedef struct _Element Element;
struct _Element {
void* data;
};
typedef struct _ArrayList ArrayList;
struct _ArrayList {
int size;
Element *elements;
};
int main() {
ArrayList *list;
list->size = 100;
list->elements = (Element*)calloc(sizeof(Element), list->size);
for (i = 0; i < list->size; i++) {
/*
* error: incompatible types when assigning to type
* ‘Element’ from type ‘void *’
*/
list->elements[i] = NULL;
}
}

Firstly, you never allocated memory for your list object! Your list pointer is uninitialized and points nowhere. Trying to apply the -> operator to it causes undefined behavior.
I don't know what your final intent is, but it should be either something like
ArrayList *list = malloc(sizeof *list);
list->size = 100;
...
or
ArrayList list;
list.size = 100;
...
Secondly, your void * pointer is actually a named field called data inside Element struct
for(i = 0; i < list->size; i++)
list->elements[i].data = NULL;
Thirdly, becuse you used calloc the memory is already sort of "initialized" with all-zero bit-pattern (including your data fileds). Formally, such bit-pattern in void * is not guaranteed to represent a null pointer, but on most platforms it actually does.
P.S. Don't cast the result of calloc
list->elements = calloc(sizeof(Element), list->size);
or event better
list->elements = calloc(sizeof *list->elements, list->size);

Apart from all the logical errors, the compiler error is the result of trying to assign a value (NULL) to a struct-typed variable. The fact that the struct contains a void * is coincidental. You'd get the same error with:
typedef struct _Element Element;
struct _Element{
int data;
};
Element e;
e = NULL;
This is most likely a mistake from what you intended to do, which is assign a value to the variable inside the struct:
for(i = 0; i < list->size; i++)
list->elements[i].data = NULL;

Related

Transferring data from queue to array

I'm trying to put integer data from each node in a queue into an array called arr. The data for each node is inputted by the user, say there's 5 nodes, and has 1 2 3 4 5, where node 1 stores a value of 1 and node 5 stores a value of 5. My code is below:
typedef struct linkedList {
int val;
struct linkedList *next;
} list;
I've tried doing the following but I'm getting a few warnings when I compile the code, I only included the body of the function and not the header or prototype and such.
int i;
int *arr;
list *node = NULL;
for(i = 0; i < 5; i++) {
arr[i] = (int*)malloc(sizeof(int));
arr = node->id;
node = node->next;
}
The errors that I get are: warning: assignment to ‘int *’ from ‘int’ makes pointer from integer without a cast and warning: variable ‘arr’ set but not used
How do I actually get the data from the queue into an array so that the array is arr[0]=1 and arr[4]=5]? Thanks.
Assuming you already have your linked list allocated correctly and you know the number of nodes (since you didn't post the code for your linked list) then your copy to array function should look like this.
int* copylist(struct LinkedList* ls,int numberofnodes){
int* arr = malloc(sizeof(int)*numberofnodes);
for(int index = 0; index < numberofnodes; ++index){
arr[index] = ls->val;
ls = ls->next;
}
return arr;
}

Cannot allocate dynamic array on C

Im trying to create a graph structure on C but I got some issues. First, Im getting 2 compilation errors:
main.c:18:19: error: member reference type 'node' is not a
pointer; did you mean to use '.'?
graph[index]->start = NULL;
~~~~~~~~~~~~^~
.
main.c:18:27: error: expression is not assignable
graph[index]->start = NULL;
~~~~~~~~~~~~~~~~~~~ ^
2 errors generated.
compiler exit status 1
I cannot figure out what Im doing wrong. I tried to create an array of nodes* but the compiler doesn't recognize it as a pointer for some reason. It's like malloc doesn't work. Also, I can't manage to acess edge* fields because it's like the array of nodes* is non-existent.
#include <stdio.h>
#include <stdlib.h>
#define maxNodes 4
typedef struct edge {
int target;
struct edge* next;
} edge;
typedef struct {
edge* start;
} node;
void initializeGraph(node* graph) {
graph = (node *) malloc(maxNodes * sizeof(node));
for(int index = 0; index < maxNodes; index++) {
graph[index]->start = NULL;
}
}
int main(void) {
node test;
initializeGraph(&test);
}
Im trying to initialize my structure. Any help is appreciated.
You have a large number of problems in your short example code. As to your error, that is covered by #dbush's answer and [...] serves as a dereference on your pointer making the '.' (dot) operator proper instead of the -> arrow operator.
Next, you cannot declare a node with static storage duration in main() and pass its address for allocation in your function. When you declare node test; all storage is already provided on the stack. You can't then pass that address to your function and allocate additional memory for that struct.
If you intend to have more than one node, then you can either declare an array with static storage duration in main(), or you must declare a pointer in main() and allocate in your function. To make that allocation visible in main(), as noted in my comment, you can either (1) make the return type node * and return a pointer to the allocated block for assignment in the caller, or (2) make the parameter node** and pass the address of your pointer as the parameter.
Putting that altogether and choosing option (1) above, you could do:
#include <stdio.h>
#include <stdlib.h>
#define maxNodes 4
typedef struct edge {
int target;
struct edge* next;
} edge;
typedef struct {
edge* start;
} node;
node *initializeGraph (void) {
node *graph = malloc(maxNodes * sizeof *graph);
if (!graph)
return NULL;
for (int index = 0; index < maxNodes; index++) {
graph[index].start = NULL;
}
return graph;
}
int main (void) {
node *test = initializeGraph();
if (!test)
fputs ("error: initialization failed.\n", stderr);
else
puts ("initialization succeeded");
}
Example Use/Output
$ ./bin/graphinit
initialization succeeded
Allocating For Each test[i].start
Before you can make use of any of the start pointers, you must allocate storage for a struct edge and assign the beginning address for that block of memory to each of your test[i].start pointers. You can do that in your same initializeGraph() function by allocating where you currently set the pointers NULL, e.g.
node *initializeGraph (void)
{
node *graph = malloc(maxNodes * sizeof *graph);
if (!graph)
return NULL;
for (int index = 0; index < maxNodes; index++) {
graph[index].start = malloc (sizeof *graph[index].start);
if (!graph[index].start)
return NULL;
}
return graph;
}
You can then assign a value to the target in each. Extending the earlier example, you could do:
int main (void) {
node *test = initializeGraph();
if (!test)
fputs ("error: initialization failed.\n", stderr);
else
puts ("initialization succeeded");
for (int i = 0; i < maxNodes; i++)
test[i].start->target = i;
puts ("targets filled");
}
Example Use/Output
$ ./bin/graphinit
initialization succeeded
targets filled
(don't forget to free the memory you allocate when it is no longer needed)
Look things over and let me know if you have further questions.
The array index operator [] implicitly dereferences a pointer. The syntax a[b] is exactly the same as *(a + b).
This means that graph[index] has type node, not node *. So use . instead of -> as the error message suggests.
graph[index].start = NULL;

First element in a double pointer to struct is jiberrish

I am creating a simple array of structures in C, but the first structure is always jibberish. How do i fix this?
I have tried to set the first element of the double pointer to struct in many ways but it always fails.
This is my graph.h file:
#ifndef GRAPH_H
#define GRAPH_H
#include "set.h"
typedef struct urlNode * URLList;
typedef struct GraphRep * Graph;
struct urlNode {
int id;
char* URL_NAME;
URLList next; // link to next node
};
struct GraphRep {
int nV;
URLList * collections;
};
Graph newGraph(Set s);
int nameToId(Graph g, char *name);
void showGraph(Graph g);
#endif
And my newGraph(Set s) function looks like this:
Graph newGraph(Set s){
int size = nElems(s);
Graph new_graph = malloc(sizeof(struct GraphRep));
if (new_graph == NULL) {
printf("ERROR: COULDNT ALLOCATE GRAPH\n");
}
new_graph->nV = size;
char *name = getNextVal(s);
// THIS IS THE NODE TO BE ADDED TO THE GRAPH
URLList list_to_add = malloc(sizeof(struct urlNode));
list_to_add->URL_NAME = strdup(name);
list_to_add->id = 0;
list_to_add->next = NULL;
// HERE I ADD THE NODE TO THE GRAPH.
new_graph->collections[0] = list_to_add;
// PRINT OUT THE VALUES OF THE NEWLY ADDED NODE TO MAKE SURE IT WORKS
// THE URL_NAME IS PRINTED OUT FINE
// BUT THE ID IS JIBBERISH.
printf("%s\n", new_graph->collections[0]->URL_NAME);
printf("%d\n", new_graph->collections[0]->id);
if(new_graph->collections[0]->next != NULL) {
printf("%s\n", new_graph->collections[0]->next->URL_NAME);
printf("%d\n", new_graph->collections[0]->next->id);
}
printf("\n");
return new_graph;
}
I expect new_graph->collections[0]->id to be 0 but it keeps on giving me random ints.
Also even if the next for the newly declared pointer to struct is NULL, it still gives me a jibberish next value too.
Any help would be appreciated, thanks!
The data member collections of the object *new_graph is not initialized.
There is initialized only this data member
new_graph->nV = size;
So this statement
new_graph->collections[0] = list_to_add;
results in undefined behavior.
If you need an array of pointers of the type URLList you have to allocate the memory and its address assign to the pointer collections.
For example
new_graph->collections = malloc( new_graph->nV * sizeof( URLList ) );
And after that this statement
new_graph->collections[0] = list_to_add;
could be valid.
(I suppose that the data member nV corresponds to the number of elements in the dynamically allocated array though it may not be truth)
Pay attention to that as the string pointed to by the pointer name is not changed in the function then it is better to declare it like
const char *name = getNextVal(s);

Creating array of pointers

I need to create an array to pointers of pNodes but when i declare it i dont know the length of the array
lets see what i mean
this is the Node struct
typedef struct _Node {
struct _Node* next;
pElement element;
} Node, *pNode;
this is the Hash struct
typedef struct _Hash {
int hashSize;
pNode *hashTable;
}Hash,*pHash;
now i want each of the
hashTable boxes to point to a pNode
the problem is that i dont know the size of the array, if i did it would be like (i guess)
pNode hashTable[hashSize]
the way i wrote it and tried to resett all boxes to NULL:
this is the CODE:
allocation memory:
pHash hash = (pHash)(malloc(sizeof(Hash)));
hash->hashTable = (pNode)(malloc(sizeof(pNode) * size));
hash->hashSize = size;
resetHashTable(hash->hashTable, size); // reseting the array to NULLS
the func:
static void resetHashTable(pNode *hashTable, int size) {
int i;
for (i = 0; i < size; i++) {
hashTable[i] = (pNode)NULL;
}
}
one of the many many errors i get from the program is (the first error)
hash.c:37:18: warning: assignment from incompatible pointer type [enabled by default]
hash->hashTable = (pNode)(malloc(sizeof(pNode) * size));
can i have some pointers how i need to write it?
If this is not C++ just don't cast malloc, you have an error in this line
hash->hashTable = (pNode)(malloc(sizeof(pNode) * size));
It could be
hash->hashTable = (pNode *)(malloc(sizeof(pNode) * size));
// ^ hashTable is declared pNode *
A better solution would be
hash->hashTable = malloc(sizeof(pNode) * size);
You are declared the pNode as a pointer. Then in Hash structure You are declared the pNode * hastable So you have to use the double pointer **. Or else make that as single pointer in hash structure.
hash->hashTable = (pNode*)(malloc(sizeof(pNode) * size));

function argument a pointer array (C)

in my code I have a array of pointers, where the pointers point to my struct
struct Container *bucket[sizeOfHashMap];
I have a function that will return 1 of these array pointers (e.g it may return the pointer at array index 6). As an argument it wants a pointer to this pointer. The function can be seen here:
struct Container* getWhichBucket(char word[], struct Container **bucket[10]){
int value = 0;
int i = 0;
int size = strlen(word);
int hashIndex = 0;
for(i =0; i < size; i++){
value += (int)word[i];
}
//size of array is worked out by getting memory that array takes up / a slot
hashIndex = value % sizeOfHashMap;
return *bucket[hashIndex];
}
I call the function like this (where test is an array of characters)
addToBucket(test, getWhichBucket(test, &bucket));
the add to bucket looks like this:
void addToBucket(char word[], container **bucket){
container *temp = (struct Container*)malloc (sizeof(struct Container));
strcpy(temp->key, word);
temp->value = 9001;
temp->next = *bucket;
*bucket = temp;
return;
}
However the compiler issues warnings when I compile the code and when I run it I get a segmentation error. Does anyone know why? The warnings can be seen here:
cw.c: In function ‘main’:
cw.c:86:2: warning: passing argument 2 of ‘getWhichBucket’ from incompatible pointer type [enabled by default]
cw.c:37:19: note: expected ‘struct Container ***’ but argument is of type ‘struct Container * (*)[(long unsigned int)(sizeOfHashMap)]’
cw.c:86:2: warning: passing argument 2 of ‘addToBucket’ from incompatible pointer type [enabled by default]
cw.c:56:6: note: expected ‘struct container **’ but argument is of type ‘struct Container *’
addToBucket(test, getWhichBucket(test, &bucket));
is passing a
struct Container *(*)[10]
to getWhichBucket. That's the wrong type, as the compiler says.
You can fix the prototype and implementation
struct Container* getWhichBucket(char word[], struct Container *(*bucket)[10]){
int value = 0;
int i = 0;
int size = strlen(word);
int hashIndex = 0;
for(i =0; i < size; i++){
value += (int)word[i];
}
//size of array is worked out by getting memory that array takes up / a slot
hashIndex = value % sizeOfHashMap;
return (*bucket)[hashIndex];
}
or change the call, but there's no easy way to get a struct Container **bucket[10] from a struct Container *bucket[10], so then you'd probably still want to change the type and implementation of getWhichBucket.
Since you're not modifying the bucket argument there, there's no need to pass the address, you can simply pass the struct Container *bucket[10] directly,
struct Container* getWhichBucket(char word[], struct Container *bucket[]){
int value = 0;
int i = 0;
int size = strlen(word);
int hashIndex = 0;
for(i =0; i < size; i++){
value += (int)word[i];
}
//size of array is worked out by getting memory that array takes up / a slot
hashIndex = value % sizeOfHashMap;
return bucket[hashIndex];
}
and call
addToBucket(test, getWhichBucket(test, bucket));
You need to change your declaration of addToBucket from
void addToBucket(char word[], container *bucket)
{
container *temp = (struct Container)malloc (sizeof(struct Container));
strcpy(temp->key, word);
temp->value = 9001;
temp->next = *bucket;
*bucket = temp;
return;
}
to
void addToBucket(char word[], Container *bucket)
{
Container *temp = malloc (sizeof(struct Container));
strcpy(temp->key, word);
temp->value = 9001;
temp->next = *bucket;
*bucket = temp;
return;
}
Note the change in case for Container -- case matters in C... container is not the same thing as Container.
Also... note... you should not cast malloc in C.

Resources