Cannot allocate dynamic array on C - 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;

Related

Error while accessing array of pointers to structures

I am trying to make an array of structures in which each array elements itself points to another structure of the same type. In order to better explain the problem, I have made a schematic for it! The names of the variables are according to the code (shown below)
But I am getting an error while I am freeing the memory! Can someone provide some hints for solving this! Thanks.
Error:
tempCodeRunnerFile.c:36:42: error: member reference type 'Vertex *' (aka 'struct Node *') is a pointer; did you mean to use '->'?
Vertex* ptr = (*(vertexarray+ i)).next;
~~~~~~~~~~~~~~~~~~~^
->
tempCodeRunnerFile.c:57:14: warning: incompatible pointer types passing 'Vertex [4]' to parameter of type 'Vertex **' (aka 'struct Node **') [-Wincompatible-pointer-types]
finalize(vertexarray);
^~~~~~~~~~~
tempCodeRunnerFile.c:30:24: note: passing argument to parameter 'vertexarray' here
void finalize(Vertex** vertexarray){ // free the dynamic memmory
^
1 warning and 1 error generated.
Code:
#include <stdio.h>
#include <stdlib.h>
// Data structure to store a linked list node
typedef struct Node
{ int data;
struct Node* next;
}Vertex;
Vertex* initialize(); //Vertex** vertexarray
void finalize(Vertex** vertexarray);
Vertex* initialize(){ // initialise the elements inside the array
Vertex* node = (Vertex*)malloc(sizeof(Vertex));
if(node ==NULL){
printf("Error in initialising"); // If node cannot be created due to memmory issues.
return NULL; // listhead is NULL
}
else{
node->data = -1; // The initial node is empty (contains data value -1, symbolising empty).
node->next = NULL; // The list at the time of initialisation is empty and hence no node to further point on.
}
return node;
}
void finalize(Vertex** vertexarray){ // free the dynamic memmory
int i;
for (i=0; i<4;i++){ // free all the memmory
Vertex* ptr = (*(vertexarray+ i)).next;
Vertex* tmp;
while( ptr!= NULL) // Termination condition: At the end, the pointer is not pointing to any node, but a NULL value
{
tmp = ptr; // make tmp the current node starting from listhead.
ptr = ptr->next; // update the pointer to the next pointer
free(tmp); // free the previous pointer
}
}
}
int main(void)
{
Vertex vertexarray[4];
int i;
for (i=0; i<4;i++){
vertexarray[i].next = initialize();
}
finalize(vertexarray);
return 0;
}
As the finalize method would need to free every element of the array you could write it like this
void finalize(Vertex vertexarray[], size_t len)
{ // free the dynamic memmory
int i;
for (i = 0; i < len; i++)
{ // free all the memmory
Vertex *ptr = vertexarray[i].next;
Vertex *tmp;
while (ptr != NULL) // Termination condition: At the end, the pointer is not pointing to any node, but a NULL value
{
tmp = ptr; // make tmp the current node starting from listhead.
ptr = ptr->next; // update the pointer to the next pointer
free(tmp); // free the previous pointer
}
}
}
And call it in main as
finalize(vertexarray, 4);
It will still work if vertexarray will allocated dynamically as you still need to keep track of how many elements has. Unless you change the vertexarray to also be a list

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);

Initializing C struct using pointer to pointer

I'm working on creating a hash table implementation for an assignment. I've defined my hashtable as struct as follows:
typedef struct hashtable {
int size;
int entries;
int table*; // pointer to table. Each entry will point to linked list
// of key-value nodes
} hashtable;
I have to initialize the hashtable struct in a method using double pointers, e.g.:
void init(hashtable** ht) {
...
}
I've written a basic implementation below:
#include <stdio.h>
#include <stdlib.h>
typedef struct hashtable {
int size;
int entries;
int table*; // pointer to table. Each entry will point to linked list
// of key-value nodes
} hashtable;
void init(hashtable**);
void init(hashtable** ht) {
*ht = (hashtable *) malloc( sizeof(hashtable) );
*ht->size = 3;
}
int main(){
hashtable *t = NULL;
init(&t);
printf("t.size: %i", t->size);
}
However, I keep getting the following compile error:
ll.c:19:8: error: member reference base type 'hashtable *' (aka 'struct hashtable *') is not a
structure or union
*ht->size = 3;
~~^ ~~~~
1 error generated.
So I'm confused by the following:
1. I'm not sure how to create a new struct in the init function when being passed a pointer to pointer.
2. After allocating the struct, how do I modify the struct member attributes?
This is just a operator precedence problem.
The compiler processes -> before the *. Therefore, it tries to access the size member of struct hashtable ** which is not possible.
The code compiles if you exchange *ht->size with (*ht)->size.
You have 2 errors in your code :
int table* --> int *table - Declare pointer to integer
*ht->size --> (*ht)->size - Imp to put brackets when you are not sure of operator precedence
That's a good start, and others have addresses the primary issues in your code. However, I would suggest a minor tweak:
#include <stdio.h>
#include <stdlib.h>
typedef struct hashtable {
int size;
int entries;
int table*; // pointer to table. Each entry will point to linked list
// of key-value nodes
} hashtable;
// note: freeing the hashtable is a caller responsibility!
hashtable *new_hashtable() {
hashtable *ht = malloc( sizeof(hashtable) );
ht->size = 3; // since ht is only a single pointer, no need for (*ht)->foo
return ht;
}
int main(){
hashtable *ht = new_hashtable();
printf("ht.size: %i", ht->size);
free(ht);
}
The problem is that
-> has higher precedence than * in C as you can see from here
using precedence rules *ht->size translates to *(ht->size). That should make clear the reason why you get the error. Another way to see it is
*(ht->size)=(*(*ht).size)
Fix this using parenthesis as follows: (*ht)->size
There is another issue in the definition of hashtable:
int table*; won't compile. Use int *table; instead to declare a pointer to int?
Thanks all for the quick response. For future reference, here's a quick update of the original code with solutions:
#include <stdio.h>
#include <stdlib.h>
typedef struct hashtable {
int size; // size of hash table
int entries; // number of slots allocated in table
int *table; /* pointer to table. Each entry will point to linked list
of key-value nodes */
} hashtable;
void init(hashtable**);
void init(hashtable** ht) {
*ht = (hashtable *) malloc( sizeof(hashtable) );
(*ht)->entries = 0;
(*ht)->size = 3; //replace this with better init size, ideally a prime number
(*ht)->table = malloc( (*ht)->size * sizeof(int));
}
int main(){
hashtable *t = NULL;
init(&t);
t->table[2] = 3;
printf("t.size: %i \n", t->size);
printf("t.arr:[2] %i \n", t->table[2]);
free(t);
}

Initialization of a structure that contains a pointer to an array

I have the following structure:
typedef struct TRIE_NODE
{
char* word;
struct TRIE_NODE* node[26];
}TRIE_NODE;
I create a node called head, TRIE_NODE *head = NULL;, and then i try to initialize this node using the following function:
void initialize_node(TRIE_NODE *current_node)
{
int MAX = 25;
current_node = malloc(sizeof(TRIE_NODE));
for(int i = 0; i < MAX; i++)
{
current_node->node[i] = NULL;
if(current_node->node[i] == NULL)
printf("\n -- \n");
}
}
However, i get a segmentation fault whenever i try to even read current_node->node[i]. Does anyone have any idea of what's going on? Considering current_node->node is a pointer, that points to another pointer of type TRIE_NODE, shouldn't i be able to access it's values through bracket notation? (I've tried dereferencing it too, it doesn't compile)
You do everything correctly, except this line
current_node = malloc(sizeof(TRIE_NODE));
which modifies the local copy of current_node. The pointer in the caller remains unchanged.
To fix this problem, pass a pointer to pointer, and assign with an indirection operator:
void initialize_node(TRIE_NODE **current_node_ptr) {
...
*current_node_ptr = malloc(sizeof(TRIE_NODE));
...
}

user input in struct in C?

int a;
scanf("%d",a);
typedef struct mylist {
int info[a];
struct mylist *link;
} Node;
this is my very simple struct and variable 'a' that don't work.
The thing which I want my program to do is to read input from the user and insert the digit into the struct (the user can determine the size of the array), however, I don't know how to do it since I get an error:
"variably modified ‘info’ at file scope".
I want to know whether it is possible to do this in a simple way.
When you use scanf into an integer you must pass a pointer. You may want to check the documentation.
scanf("%d", &a);
As far as using a variable to allocate data, you can do it, but you will want to use malloc most likely after defining your structure as a type.
As pointed out by #David Hoelzer
scanf("%d",a);
should be
scanf("%d",&a);
If you are under C99 you can use flexible array members:
typedef struct mylist {
struct mylist *link;
int info[]; /* should be the last member */
} Node;
and then
Node *node = malloc(sizeof *node + (a * sizeof(int)));
You must have pointer to array of correct size or use flexible array. Here is how to use a pointer initializing it to point to storage of proper size.
struct mylist {
int *info; // or int info[] at the end of struct def if C99 is used
int info_size;
struct mylist *link;
};
int main(void)
{
int *array;
struct mylist m;
if (scanf("%d", &m.info_size) != 1)
{
perror("scanf failed");
exit(EXIT_FAILURE);
}
// ok
array = malloc(sizeof(int) * m.info_size);
if (array == NULL)
{
perror("malloc failed");
exit(EXIT_FAILURE);
}
// ok, commit changes
m.info = array;

Resources