I have an array of structs called arrayOfElements , the structs are called Elements which have a void pointer
typedef struct {
void* data;
} Element;
Ive malloc'd arrayOfElements
Element* arrayOfElements;
arrayOfElements= malloc(4 * sizeof(Element));
and have stored ints and strings in the strucs
arrayOfElements[3].data = malloc( sizeof(int) );
ptr = arrayOfElements[3].data;
*ptr = 65;
strcpy(arrayOfElements[1].data, token );
Then I have created a Linked List
typedef struct LinkedList {
void* arrayOfStruct;
struct LinkedList* next;
} LinkedList;
And have created a function to import a instance of arrayOfELements and make void* arrayOfStruct point to it
LinkedList* insert(LinkedList* head, Element* inArrayOfElements) {
LinkedList* insertNode = malloc(sizeof(LinkedList));
insertNode->next = head;
insertNode->arrayOfStruct = (void*)inArrayOfElements;
return insertNode;
}
Question
My question is after I have pointed void* arrayOfStruc to an instance of arrayOfELements, how do I print void* data of arrayOfElements[3] which I know from before is an int and its value is 65
Current Node in LinkedList ---> arrayOfElements[3] --> data member in Element struct (should equal 65)
I have a feeling I should point a int pointer to it and then print that, but Im not sure the syntax to do it
You need some way of knowing what kind of data the data member points to. An additional element denoting the type would work.
typedef enum {
STR_TYPE,
INT_TYPE,
...
} data_type;
typedef struct {
data_type type;
void* data;
} Element;
Then you can set the element like this:
arrayOfElements[3].type = INT_TYPE;
arrayOfElements[3].data = malloc( sizeof(int) );
int *ptr = arrayOfElements[3].data;
*ptr = 65;
arrayOfElements[1].type = STR_TYPE;
strcpy(arrayOfElements[1].data, token );
and read it like this:
Element *curr = &list_node->arrayOfStruct[3];
if (curr->type == INT_TYPE) {
int *pint = curr->data;
printf("int data = %d\n", *pint);
}
Related
This question already has an answer here:
Dynamic memory access only works inside function
(1 answer)
Closed 8 months ago.
pointer to a struct
code that can not work
struct node
{
/* data */
int data;
};
void addnode(struct node* n)
{
n = (struct node*)malloc(sizeof(struct node));
printf("value of pointer n = %p",&n);
(*n).data = 9;
}
int main()
{
struct node * n1 = NULL;
addnode(n1);
printf("data is %d\n",n1->data);
}
but the code below is fine
struct node
{
/* data */
int data;
};
void addnode(struct node ** n1)
{
// the address of struct
*n1 = (struct node*)malloc(sizeof(struct node));
printf("address of pointer &n1 = %p\n",&n1);
printf("address of pointer *n1 = %p\n",*n1);
(*n1)->data = 99;
}
int main()
{
struct node * n1 = NULL;
//pass the address of pointer instead of value of it
addnode(&n1);
printf("address of pointer &n1 = %p\n",&n1); // self address
printf("address of pointer *n1 = %p\n",&(*n1)); // the address of struct
printf("data is %d\n",n1->data);
}
what makes me confused is why the indirect pointer as a parameter is working, instead of the direct pointer.
The 'indirect' pointer, as you called it, is actually 'a pointer to your pointer variable'.
If you inspect the value of n1 in your debugger, you will see, in your first example, that it will remain NULL (because you did not assign a new value to it).
In the second example however, you assign a value to the variable by accessing it's address.
Your first code can work too if it looks like this:
struct node
{
/* data */
int data;
};
struct node* addnode()
{
struct node* n = (struct node*)malloc(sizeof(struct node));
printf("value of pointer n = %p",&n);
n->data = 9;
return n;
}
int main()
{
struct node * n1 = NULL;
n1 = addnode();
printf("data is %d\n",n1->data);
}
#include <stdio.h>
#include <stdlib.h>
typedef struct nodeWords
{
char * word;
int index;
struct nodeWords *left;
struct nodeWords *right;
} nodeWords;
int main(void)
{
nodeWords * node = malloc(sizeof(*node));
printf("%lu\n",sizeof(*node));
node->left = NULL;
node->right = NULL;
nodeWords * ihash = malloc(2 * sizeof(*ihash));
printf("%p \n", node->left);
//this part not working
ihash[0] = *node->left;
printf("%p\n",ihash[0]);
}
How can I assign node->left to ihash[0] and then be able to print out ihash[0], which should point to NULL?
There are two errors in your code and a few other 'minor issues' (I've commented these in the code posted below).
The first error is that you want to create an array of pointers to nodeWords, so you will need two stars in the declaration of ihash (one star will create an array of structure objects).
Second, in ihash[0] = *node->left;, you are dereferencing node twice (once with the preceding star operator, and once again with the -> operator.
The following code fixes these issues:
#include <stdio.h>
#include <stdlib.h>
typedef struct nodeWords {
char* word;
int index;
struct nodeWords* left;
struct nodeWords* right;
} nodeWords;
int main(void)
{
nodeWords* node = malloc(sizeof(*node));
printf("%zu\n", sizeof(*node)); // Should really use "%zu" for size_t
node->left = NULL;
node->right = NULL;
nodeWords** ihash = malloc(2 * sizeof(*ihash)); // You want an array of POINTERS so you need two ** in the type!
printf("%p \n", (void*)node->left); // Pedantic: %p expects a void*
//this part not working
ihash[0] = node->left; // The "*" preceding "node" was an error: the "->" inherentlt derefernces node
// ihash[0] = (*node).left; // An alternative way of dong the same thing
printf("%p\n", (void*)ihash[0]); // Pedantic: %p expects a void*
// Don't forget to free the allocated memory...
free(ihash);
free(node);
return 0; // Always good practice to put this EXPLICIT return statement in your "main"
}
Generally, I know that a pointer stores the memory address of another value located in computer memory, for example:
int firstvalue= 5
int * p1;
p1 = &firstvalue; // p1 = address of firstvalue
What happens if we define an operation like the following in a linked list? Does *current=*list means that the value pointed to by current equals to the value pointed to by list? And what does it mean if we define ecur=current?
int function(struct list_t **list){
struct list_t *ecur=NULL;
struct list_t *current=*list;
ecur=current;
}
Update:
What does it do *list=remove(*list, param1, param2)? And why is that?
remove is a function that returns a modified list of list.
Update 2:
Why do we need to define a pointer to pointer in order to modify the list? Is *list a pointer to pointer?
The variable list is a pointer to a pointer to a struct list_t. If we (just as an example) assume that the struct is placed at address 2000 and that the unnamed pointer is at address 1000 it will look like this:
Then you have the initialization that adds two new variables. Both as pointer to a struct list_t.
struct list_t *ecur=NULL;
struct list_t *current=*list;
So the picture now becomes:
Notice that current got the same value as the "some-pointer" in the middle because it is *list that was assigned to current.
Then you have the assignment:
ecur=current;
which means that ecur gets the same value as current and gives the picture:
Update: What does it do *list=remove(*list, param1, param2) ?
It changes the value of the "some-pointer" in the middle of the picture. This is for instance needed if the remove function removes the first element in a linked list.
Why do we need to define a pointer to pointer in order to modify the list? Is *list a pointer to pointer?
Remember that C passes all function arguments by value - the formal argument in the function definition is a different object in memory from the actual argument in the function call. For example:
void swap( int a, int b )
{
int tmp = a;
a = b;
b = tmp;
}
void foo( void )
{
int x = 1;
int y = 2;
swap( x, y );
}
a is a different object in memory than x, and b is a different object in memory than y, so swapping a and b has no effect on x and y. In order to swap the values of x and y, you must pass pointers to them:
void swap( int *a, int *b )
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void foo( void )
{
int x = 1;
int y = 2;
swap( &x, &y );
}
The expression *a is the same as x, so writing to *a is the same as writing to x. Same for *b and y.
So, in order for a function to write to a parameter, you must pass a pointer to that parameter:
void foo ( T *arg )
{
*arg = new_value(); // writes a new value to the thing arg points to
}
void bar( void )
{
T var;
foo( &var ); // write a new value to var
}
This is true for any non-array type T. Let's replace T with a pointer type P *:
void foo( P **arg )
{
*arg = new_value(); // write a new *pointer* value to the thing arg points to
}
void bar( void )
{
P *var;
foo( &var ); // write a new pointer value to var
}
The semantics are exactly the same - all that's changed is the type.
If a function has the potential to modify a list * object (say pointing it at a new list head), then you must pass a pointer to that list * object:
void add_node( struct list_t **list, struct list_t *node )
{
if ( !*list || (node->value < (*list)->value) ) // make node new head of list
*list = node;
else
// add node somewhere else in the list
}
int main( void )
{
struct list_t *list = NULL;
...
struct list_t *node = newNode( value );
add_node( &list, node );
...
}
TYPE *p = ptype /*variable of type: TYPE * */;
is not an assignment. It's an initialization, which for an auto-matic (=on-the-stack) p can be rewritten as:
TYPE *p;
p = ptype;
(not TYPE *p; *p=ptype; /*would be a type error*/)
In terms of your example:
struct list_t *current=*list;
sets where current will point to (the same place as what *list points to (*list is also a pointer because list is a doubly-indirect pointer)) without doing anything whatsoever with what current will point at (*current) after the initialization.
All of this is just conceptual, though. Your function doesn't have any externally visible effects so an optimizing compiler should completely delete its body.
I had a similar knot in my head with this post. I'd like to rearrange your function a bit, so it's easier to understand what's going on:
int function(struct list_t **list)
{
struct list_t *current = *list;
struct list_t *ecur = current;
}
If we call this function with an element foo we essentially get this:
struct list_t foo = { .data = "foo" };
struct list_t *bar = &foo;
struct list_t **list = &bar;
struct list_t *current = *list;
struct list_t *ecur = current;
We have five declarations and five assignments. For better readability, I'll write everything down without declarations:
foo = { .data = "foo" };
bar = &foo;
list = &bar;
current = *list;
ecur = current;
Now, let's walk through it:
foo is a struct. It contains the above data-field.
bar is a pointer to struct. It contains the address of foo
list is a pointer to a pointer to struct. It contains the address of bar
current is a pointer to struct. It contains the contents of the contents of list, which is the address of foo
ecur is a pointer to struct. It's identical to current and contains the address bar
In the end we can simplify the whole example to this:
struct list_t foo = { .data = "foo" };
struct list_t *ecur = &foo;
What does it all mean?
list: Because list is a pointer to a pointer you are able to modify bar to point to something completely different, by de-referencing it (*list = ...)
current/ecur: that's what bar originally pointed too. By de-referencing you could change the data-field itself ((*ecur).data = "banana" or better ecur->data)
I hope I could clarify things and didn't make it worse ;)
Why do we need to define a pointer to pointer in order to modify the
list?
Let me add a complete program, albeit short, to illustrate it better. It defines a simply linked list and builds it while keeping it ordered. Yes, I know it would be easier to simply call qsort(), but I want to demonstrate how adding one level of indirection —the pointer to pointer— allows to insert elements smoothly, without testing for special cases.
// C pointer exercise: sort arguments
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
struct list
{
char *arg;
struct list *next;
};
int main(int argc, char *argv[])
{
// pointer to base, running pointer and pointer to pointer
struct list *base = NULL, *p, **pp;
for (int i = 1; i < argc; ++i)
{
struct list *new_entry = malloc(sizeof(struct list));
if (new_entry)
{
new_entry->arg = argv[i];
// find where to insert new entry
for (pp = &base; *pp; pp = &(*pp)->next)
if (strcasecmp(new_entry->arg, (*pp)->arg) < 0)
break;
// insertion in a simply linked list
new_entry->next = *pp;
*pp = new_entry;
}
}
// display and cleanup
for (p = base; p;)
{
struct list * tmp = p->next;
puts(p->arg);
free(p);
p = tmp;
}
return 0;
}
I have a struct called warehouse and a generic linked list and each item points to a warehouse struct.
typedef struct linked{
char type;
void * item;
struct linked * next;
struct linked * prev;
}LinkedList;
typedef struct warehouse{
char * name;
float volume;
float (* getPrice) (void * S);
float (* getTotalDollarAmount)(void * S);
}house_t;
When I tried to get the getPrice function pointer point to a function float price (void *S)
void menu (LinkedList *house){
char *c;
float num;
c = (char*)malloc(sizeof(char)*10);
LinkedList *i;
i = (LinkedList*)malloc(sizeof(LinkedList);
house_t *sk;
sk = (house_t *) malloc(sizeof(house_t));
//i->item = (house_t *) malloc(sizeof(house_t));
scanf("%c", c);
((house_t*)i->item)->getPrice = price;
sk=findhouse(house, c);
num = ((house_t*)i->item)->getPrice(sk);
printf("%f",num);
}
I got bad access error. Since every time I got a bad access error it was because I didn't allocate memory for something. But do I need to allocate memory for function pointer? If so, how?
Here's some more code
float price (void *S)
{
return ((house_t*)S)->volume;
}
LinkedList *i;
i = NewLinkedList();
/* ... snip ... */
LinkedList *NewLinkedList()
{
return NULL;
}
According to your definition of NewLinkedList(), the variable i is now NULL. You try and dereference it with i->item = ... but you can't do this if i is NULL. I think what you really want to do is allocate space for your linked list in your NewLinkedList function:
LinkedList * NewLinkedList()
{
LinkedList *result = malloc(sizeof(LinkedList));
result->type = '\0'; // set to suitable initial value
result->item = NULL;
result->next = NULL;
result->prev = NULL;
return result;
}
i dont know why the list returned is NULL, this is the code:
In my List.h
struct nodo_ {
char* dato;
struct nodo_ *next;
};
struct nodo_ *Lista;
/*Def list */
void createList(struct nodo_ **Lista);
in my main.c
struct nodo_ *Lista;
int main(){
createList(Lista);
while(Lista != NULL){
printf("The date is %s\n ",Lista->dato); //Error here now
Lisa = Lista->next;
}
return 0 ;
}
in my List.c im create the List :
void createList(struct nodo_ *Lista){
struct nodo_ *Aux_List = list_D;
aux_List = malloc(sizeof(struct nodo_));
char* path_a = "Hello";
char* path_B = "Minasan";
/* Store */
aux_List->dato = path_a;
aux_List = Aux_List->next;
aux_List = malloc(sizeof(struct nodo_));
aux_List->dato = path_b;
aux_List->next = NULL;
}
Thanks.
That pointer is being passed by value, i.e., a copy is made. If you wish to initialize the pointer to a completely new value then you must use another level of indirection (i.e., a nodo_**).
On a side note, typedefing pointer types is almost always a bad idea unless the type is truly opaque (which yours is not). One reason for this "rule" is evident when you consider another bug in your code:
auxList = (Lista*)malloc(sizeof(Lista));
You're allocating space for a pointer to noda_, not enough for a noda_ object. Also, don't cast the return value of malloc in C. It is redundant as a void* is safely and implicitly converted to any other pointer type and, if you forget to include stdlib.h, malloc will be assumed to be a function which returns int, and the cast hides the error. (only applies to compilers which implement C89 or an older version)
EDIT:
To initialize a pointer argument within a function:
void init(struct node **n) {
if(n)
*n = malloc(sizeof(struct node));
}
int main() {
struct node *n;
init(&n);
}
Short answer to your actual question before I dig into the code:
... why the list returned is NULL ...
There is no returned list, you neither use return to pass a result, nor set the value of an out parameter.
In your edited code:
void createList(struct nodo_ **Lista){
struct nodo_ *Aux_List = list_D;
aux_List = malloc(sizeof(struct nodo_));
you first set Aux_List to the current value of Lista, which you know isn't initialized yet, because you're trying to initialize it. Then you discard that value, overwriting aux_List with a new address returned by malloc. You never store anything into *Lista, which would be the only way for this function to work as declared.
As Ed suggests, your typedef is hiding lots of useful information from you, so let's expand it out
struct nodo {
char* dato;
struct nodo *next;
};
/*Def list */
void createList(struct nodo* list_D);
Now, you can see this createList is wrong: you can pass in the head node of a list (which is no use to it anyway), but there is no way for it to return a newly-allocated list to the caller.
Frankly your createList isn't a useful primitive anyway, so I'm going to start with a sensible foundation first:
struct nodo *alloc_nodo(char *dato, struct nodo *next)
{
struct nodo *n = malloc(sizeof(*n));
n->dato = dato;
n->next = next;
return n;
}
Now, before we re-write your createList using this, let's see what it does now:
void createList(struct nodo *list_D)
{
struct nodo *aux_List = list_D;
aux_List = malloc(sizeof(struct nodo_));
/* ^ so, we take the input argument and immediately discard it */
char* path_a = "Hello";
char* path_B = "Minasan";
/* Store */
aux_List->dato = path_a;
aux_List = Aux_List->next;
/* ^ note that we haven't initialized aux_List->next yet,
so this is a random pointer value */
aux_List = malloc(sizeof(struct nodo_));
/* again, we set aux_List to something,
but immediately overwrite and discard it */
aux_List->dato = path_b;
aux_List->next = NULL;
}
So, it ignores its input, returns no output, and leaks two partially-initialized nodes which aren't connected to each other. I believe you wanted to achieve something more like this:
struct nodo* create_my_list()
{
struct nodo *tail = alloc_nodo("Minasan", NULL);
/* the end (tail) of the linked list has a NULL next pointer */
struct nodo *head = alloc_nodo("Hello", tail);
/* the head of the linked list points to the next node */
return head;
/* like a snake, you hold a singly-linked list by the head */
}
If we write main to use this function now, it looks like:
int main()
{
struct nodo *head = create_my_list();
struct nodo *n;
for (n = head; n != NULL; n = n->next)
{
printf("The date is %s\n ", n->dato);
}
}