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));
...
}
Related
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;
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);
I have strange problem with allocating a linked list in a loop.
Consider a simplified source code :
struct main_s {
minor_s minor_structure; (inline)
};
struct minor_s {
list_s *first_dir;
};
struct list_s {
anotherlist_s *first_object;
list_s *next;
};
struct anotherlist_s {
//multiple fields
};
And i have a basic init/deinit functions like :
struct main_s *main_s_init();
void main_s_deinit();
And now i'm kinda riddled with allocating in loop :
im passing to this function main_s->minor_structure.first_dir and, how_many parameter, defining how many linked nodes going to be initiated.
void loop_inittiation(struct list_s *list, int how_many) {
int i;
struct list_s *tmp = list;
for(i = 0; i < how_many; i++) {
tmp = malloc(sizeof(struct list_s));
tmp = tmp->next;
}
}
And this is where i have problem, im allocating the temporary "tmp" instead of the pointed structure. I understand that to allocate a pointer by tmp u have to use double pointer, but it still doesnt work. What am i missing? In gdb there is no memory space allocated :/.
Do i have to use **tmp?
You've got the right idea about what's wrong. The local copy of tmp in the function is changed, but once you're outside, that value is lost. If you want to change a variable inside a different function in C, you MUST pass the address of the thing you want to change. If the thing you want to change is already a pointer, you must pass the address of the pointer (or double pointer). If it's a double pointer you want to change, then you have to pass a triple pointer. If it's a 123141 pointer, you have to pass a 123142 pointer :)
Change the parameter to the function to:
&(main_s->minor_structure.first_dir)
Just change the input parameter to
struct list **list
change tmp to a double pointer to match it, then each time you use tmp, make sure to throw in an extra dereference..
struct list_s **tmp = list
and
*tmp = malloc(sizeof(struct list_s));
*tmp = (*tmp)->next;
So it would look like:
void loop_inittiation(struct list_s **list, int how_many) {
int i;
struct list_s **tmp = list;
for(i = 0; i < how_many; i++) {
*tmp = malloc(sizeof(struct list_s));
tmp = &((**tmp)->next);
}
}
Another way to do it is to leave the tmp stuff alone, as a single pointer, store the first node you allocate, and then just say
*list = tmp;
But then you do have to treat that first allocation as a special case.
I have a problem with my pointers and structures in C (I know, I knooww, pretty basic!). I was practicing my procedural paradigm. It's the first time I use a debugger, because I haven't really needed it earlier in my life : < so I if you please help me I'll be thankful.
I defined the following structure to make a list:
typedef struct node {
int info;
struct node *next;
struct node *prev;
} node_t;
And then this function to fill it up:
void addNodo(node_t * list, int x){
node_t * pointer;
node_t * temp;
temp = (node_t *)malloc(sizeof(node_t));
temp->info = x;
temp->next = NULL;
temp->prev = NULL;
pointer = list;
if(pointer == NULL){ //it's empty so start it
list = temp;
return;
}
if (pointer->info <= x) { //I like my lists tidy so...
while((pointer->next != NULL) && (pointer->info <= x)){
pointer = pointer->next;
}
if(pointer->next == NULL){
pointer->next = temp;
temp->prev = pointer;
return;
}
pointer->next->prev = temp;
temp->next = pointer->next;
temp->prev = pointer;
pointer->next = temp;
return;
}
}
And then, doing this:
int main(int argc, char** argv) {
node_t * list = NULL;
addNodo(list, 1);
printf("x: %d", list->info);
return (EXIT_SUCCESS);
}
It's throwing me a Segmentation Error! When I debug it everything is fun and games until it passes the ++++ line, list address goes back to 0x0 and can't get it to work. I know there's an error somewhere, but to my knowledge of pointers, it's perfectly fine. Please, detect my error and teach me some pointers.
When you call addNode() you're passing in the pointer by value. So when you change it in the body of the function the change is lost and doesn't propagate outside the function. You need to declare it as:
void addNode(node_t **pointer, int x)
and then use *pointer in the function.
And when you call ity in main, pass in &list
The problem is that you cannot modify list inside the addNodo function. In C parameters are sent by value, so the changes you are doing inside "addNodo" is local to there.
You need to change addNodo function so, it actually receives the direction where is list.
void addNode(node_t **list, int x){
...
if(*pointer==NULL){
*list = temp;
}
}
Then in your main you should use:
addNode(&list, 1);
Well, you are making the mistake of passing the address of the list by value. So all the arguments of the function are made copies of and then your addNodo() works on the copied variables. Thus the original list does not get modified.
What you should be doing while calling is this:
addNodo(&list, 1);
In the function make these changes:
void addNodo(node_t ** list, int x)
/* This will enable you to get a copy of the address of the list variable.
Please note that this is also pass by value, C does not support pass by
reference */
Then make this change:
pointer = *list;
/* this will make the pointer point to the beginning of list as now
list is a pointer to pointer type */
Hope it helps you.
BTW, please go through a standard C book (I recommend K&R) to get familiar with passing arguments in C and what happens internally.
You're making a classic mistake:
void addNodo(node_t * list, int x)
...
list = temp;
return;
list isn't changed in the caller (main())
You can change the values in the memory list points at, but you can't change the value of list and have it be seen by the caller.
In order to do that, you'd need to pass a pointer to a pointer into the function:
void addNodo(node_t **list int x)
This allows you to change what list points at by doing:
*list = temp;
Can anyone please explain why the 1st method of accessing a nested struct element inside an union in a struct works and the 2nd does not?
typedef struct element Node;
struct element
{
int type;
union
{
int value;
Node *child[2];
} u;
};
int main()
{
Node n;
Node *p;
n.type = 0;
p = n.u.child[0];
p->type = 10; // 1st method
(n.u.child[1])->type = 24; // 2nd method
return 0;
}
Try the following:
int main()
{
Node n;
Node *p;
n.type = 0;
// allocate memory for child nodes
n.u.child[0] = (Node *)malloc(sizeof(Node));
if (n.u.child[0] == NULL)
{
return 1;
}
n.u.child[1] = (Node *)malloc(sizeof(Node));
if (n.u.child[1] == NULL)
{
free(n.u.child[0]);
return 1;
}
p = n.u.child[0];
p->type = 10; // 1st method
(n.u.child[1])->type = 24; // 2nd method
// release dynamically allocated memory
free(n.u.child[0]);
free(n.u.child[1]);
return 0;
}
NOTE: Don't modify n.u.value of a Node if you've already assigned its child[] pointers. You will overwrite one of the pointers and leak that memory as well as crash if you try to access the child[] array after that. Unions are tricky -- best to avoid this sort of arrangement.
Either of those methods should be fine for accessing a nested struct element inside a union, the issue here is that you haven't allocated memory for the nodes referred to by child[0] or child[1]. (I'm surprised your "1st method" doesn't fail, too.)
Your problem has not much to do with the fact that there are unions involved.
Accessing uninitialized pointers just gives you random behavior. Sometimes it does work sometimes not. For your first access probably something just luckily happened to be in the place that you access.
Just initialize, à la C99:
Node n = { .type = 0 };
or
Node n = { 0 };
à la C89,
instead of your assignment statement. This has the advantage to initialize all components that are not mentioned to 0, thus your pointers. Then your test code should segfault happily ever after.