I am writing a program that is attempting to implement a hash table in C. It has to use a pointer to a pointer as an attribute in a struct data type. Here is the code of the relevant structs.
struct node {
char * data;
struct node * next;
};
struct hashtable {
int size;
struct node ** table;
};
Part one of question:
I have been doing a lot of research to figure out just how pointers to pointers work but I still can't seem to get my head around it. Every example I've found assigns two different pointer names to the first and second pointer. eg
x = 5;
*p = &x;
**q = &p;
What about the case above "struct node ** table;"
Is ** table the same as **q in this case?
What would the values of q , *q and **q be in this case? is q = 5 and then *q and **q work back through the addresses or is **q = 5 and *q and q store the addresses?
Part two of question:
How do I access a pointer to a pointer within another function? Here is the code I have right now.
struct hashtable * hashtable_new(int size){
struct hashtable *newTable;
if ( size < 1 )
{
return NULL;
printf("Its returning Null.");
}
else
{
newTable = malloc(sizeof(struct hashtable));
newTable -> size = size;
newTable -> table = malloc(sizeof(struct node) * size);
int i;
for (i = 0; i < size; i++ )
{
newTable -> table[i] = NULL;
}
fprintf(stderr, "Table has been created.");
return newTable;
}
};
I'm not sure I understand how to access either the pointer or the pointer to a pointer through the -> symbol. Is it "newtable -> table" or "newtable -> -> table" ?
The aim of the table is essentially to be a 2d table, where the list is primarily 1D and can spread to 2D to deal with collisions in the hashing.
End note:
Hopefully I've provided enough information to make contextual sense asking this question. Its my first time asking a question on stackoverflow so feel free to ask me extra question, provide CC or flag any mistakes I've made asking this question.
Thank you!
There are several ways to look at a pointer to a pointer. One way is as you described with
int x = 5;
int *p = &x;
int **q = &p;
After all that, the following are all true:
**q == *p == x == 5
*q == p == &x
q == &p
However, another way to look at a pointer to a pointer is as an array of pointers. For example, assume the declaration:
int *arr[10];
Except when it is the operand of the sizeof or unary & operands, the expression arr will be converted ("decay") from type "10-element array of int *" to "pointer to int *", or int **.
If you want to dynamically allocate an N-element array of pointers to struct node, you would write
struct node **arr = malloc( sizeof *arr * N );
You would use the [] subscript operator to access elements in arr as you would a normal array. Since arr has type struct node **, each arr[i] has type struct node *, so you would access members of the structure like so:
arr[i]->data = "foo"; // use -> when the LHS is a pointer to a struct or union
arr[i]->next = NULL;
struct hashtable allows you to create multiple hashtable instances, each one of which has a size member and an array of struct node * which you allocate at runtime, like so:
struct hashtable h1;
h1.size = 512;
h1.table = calloc( h1.size, sizeof h1.table ); // calloc initializes all elements of
// h1.table to NULL
if ( !h1.table )
{
// calloc call failed, handle as appropriate
}
You'd insert a new element into the table like so:
/**
* Assumes we know that the string data points to is not already in
* the table. hashfunc is a pointer to the hashing function.
*/
void insert( struct hashtable *h, const char *data, size_t (*hashfunc)(const char *))
{
/**
* Create a new table entry. Remember that table is an array of
* *pointers* to struct node, and that each array element is initially
* NULL. We still need to allocate something for that table entry
* to point *to*.
*/
struct node *newNode = malloc( sizeof *newNode );
if ( !newNode )
{
/**
* Memory allocation for new node failed, handle as appropriate
*/
}
newNode->data = malloc( strlen( data ) + 1 );
strcpy( newNode->data, data );
/**
* Get the table index by computing the hash and modding against the
* table size.
*/
size_t idx = hashfunc( data ) % h->size;
/**
* Insert newNode at the head of the list starting at
* h->table[idx]. In reality you'd probably want to insert
* strings in order, but for a toy example this is good enough.
*/
newNode->next = h->table[idx]; // newNode->next points to the previous head of list
h->table[idx] = newNode; // newNode becomes new head of list.
}
When you're done, your hashtable looks something like this:
+---+
h1: | | size
+---+ +---+ +---+---+ +---+---+
| | table ----> | | --> | | | --> | | |
+---+ +---+ +---+---+ +---+---+
| |
+---+ +---+---+
| | --> | | |
+---+ +---+---+ +---+---+ +---+---+
| | --> | | | --> | | | --> | | |
+---+ +---+---+ +---+---+ +---+---+
...
table points to an array of struct node *, each of which may point to an instance of struct node, each of which may point to another instance of struct node. In the picture above, two strings have hashed to table[0],
one to table[2], and three to table[3].
Here's a little program that might help you, it might be worth playing about with pointers for a bit and inspecting them, output addresses etc.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
char *p1 = "String of text.";
char **p2;
/**
* We can print the avtual address of *p1 and **p2...
*/
fprintf(stdout, "p1 = %p\n", p1);
fprintf(stdout, "p2 = %p\n", p2);
/**
* Now if we point p2 at p1 we can then check what address
* *p2 points at...
*/
p2 = &p1;
fprintf(stdout, "*p2 = %p\n", *p2);
/**
* So if you think about it, *p2 should be the same at p1
* if we print it as a string:
*/
fprintf(stdout, "p1 is %s\n*p2 is %s\n", p1, *p2);
exit(EXIT_FAILURE);
}
Hope this helps.
As for referencing the struct from another function, if you're passing a pointer to that structure you use a single -> to refer to any member of the struct...but you are allocating another struct within your struct - using a pointer.
Say I have
struct one {
char *string;
}
struct two {
struct *one a;
struct one b;
char *whatever;
}
If have a pointer to a struct two:
struct two *t;
And it had its member a allocated a struct one...then I'd reference the members of a using ->
t -> a -> string;
But b isn't a pointer so you would do:
t -> b.string;
Related
I'm trying to implement a linked list and adding nodes to it. I encountered the following problem, when I try to free the pointer n after setting list->next to point to the same address of n, the int value inside the second node also changes to garbage value when I print it again. I want to know if inside the memory, n and list->next is stored as two separate pointers that hold the same value or it is stored as a single pointer? And if they were distinct, then why freeing n also affect list->next? Furthermore if freeing n make the second node became lost, then why I can still use the list->next->next pointer to add a third node, was list->next->next pointer also some random value that points to a random usable location ? Here is my code, sorry if my question is too vague, I'm trying my best to understand all this pointers.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
typedef struct node {
int number;
struct node *next;
} node;
int main(void) {
node a;
a.number = 1;
a.next = NULL;
node *list = NULL;
list = &a; // the first node
printf("%i \n", a.number);
node *n = malloc(sizeof(node)); // creating pointer to the second node
if (n != NULL) {
n->number = 2;
n->next = NULL;
}
list->next = n; // add the node to the list
printf("%p \n%p \n", n, list->next); // print out the address and value
printf("%i \n", list->next->number);
free(n);
printf("%p \n%p \n", n, list->next); // print out the address and value
printf("%i \n", list->next->number);
n = malloc(sizeof(node));
printf("%p \n%p \n", n, list->next);
if (n != NULL) {
n->number = 3;
n->next = NULL;
}
list->next->next = n;
printf("%i\n", (*(*(*list).next).next).number);
return 0;
}
Here is the output
1
0x5562319d62a0
0x5562319d62a0
2
0x5562319d62a0
0x5562319d62a0
1445140950
0x5562319d62a0
0x5562319d62a0
3
The assignment
list->next = n
doesn't copy the allocated memory. It just add another pointer pointing to the same memory.
If we "draw" it, before the assignment it looks something like this:
+---+ +-----------------+
| n | ---> | memory for node |
+---+ +-----------------+
Then after the assignment you have:
+---+
| n | -----------\
+---+ | +-----------------+
>--> | memory for node |
+------------+ | +-----------------+
| list->next | --/
+------------+
Then you pass n to free leading to this situation:
+---+
| n | -----------\
+---+ |
>--> ???
+------------+ |
| list->next | --/
+------------+
After the call to free, the pointer list->next is invalid. Any attempt to dereference it will lead to undefined behavior.
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 am created a struct
typedef struct t{
int top;
int value;
}s;
and another structure
typedef struct y{
int top1;
s **p
}z;
z *p1;
created a block by malloc
p1 = (z*) malloc(sizeof(z));
p1->p = (s**) malloc(10 * sizeof(s));
I tried with indexing the s structured block by
p1->p[4]->top;
but i got error. is there a way to index pointer to pointer type in C
Address them with single pointer.
typedef struct y{
int top1;
s *p; //Single pointer only
}z;
z *p1;
p1 = malloc(sizeof(z)); //Don't cast...
p1->p = malloc(10 * sizeof(s));
//And then:
p1->p[4].top;
If you still want double pointers, then:
typedef struct y{
int top1;
s **p;
} z;
z *p1;
size_t i;
p1 = malloc(sizeof(z)); //Create z structure object
p1->p = malloc(10 * sizeof(*p1->p)); //Create array of pointers to objects
//Now fill that array with your objects
for (i = 0; i < 10; i++) {
p1->p[i] = malloc(sizeof(*p1->p[i]));
}
//Now access to property as:
p1->p[4]->top; //Do something.
The second option is less preferable but depends on you, because doing single mallocfor 10 objects in a row is more efficient than doing 10x times single object and 11th time for initializing base array of pointers.
In struct y{ ...; s **p }, member p represents a pointer to a pointer to structure s, and not a pointer to structure s.
So p1->p[4] is a pointer to an s, not an s itself, so you cannot access member top with accessor .. To get around the compiler error, you would have to use accessor ->, which dereferences the pointer value, but then you yield undefined behaviour at runtime, since the pointer value is not initialized.
To solve the problem, you could either change the data type of p to s *p (as suggested by #tilz0R), or you could adapt your code to actually deal with pointers to pointers:
typedef struct t{
int top;
int value;
}s;
typedef struct y{
int top1;
s **p;
}z;
z *p1;
int main() {
p1 = malloc(sizeof(z));
p1->p = malloc(10 * sizeof(s*));
for (int i=0; i<10; i++) {
p1->p[i] = malloc(sizeof(s));
}
p1->p[4]->top = 5;
}
Note that pointers to pointers are more complicated to handle, as you need an extra step/loop to initialize the pointers and to free them later on. So actually I'd prefer the s *p-way; But sometimes pointers to pointers are more appropriate, e.g. if particular slots of the array shall remain "empty"; then you could set the respective pointer to NULL, which would not be possible in an array of struct objects.
I have an array of struts called arrayOfElements , each element being a struct called Element
typedef struct {
void* data;
} Element;
data is a void pointer as I dont know in advanced what type of variable will be stored
I've malloc'd this array to have 4 elements ( this is done by user input but ive hard coded 4 for this question)
Element* arrayOfElements;
arrayOfElements= malloc(4 * sizeof(Element));
Now to this point I can store strings and ints in arrayOfElements
Store Int
arrayOfElements[0].data = malloc( sizeof(int) );
int *ptr = arrayOfElements[0].data;
*ptr = 65;
Store String
arrayOfElements[0].data = malloc( strlen(str) + 1 );
strcpy( arrayOfElements[0].data, str );
And that all works. My Issue is how do I got about making a linked List and making each element store an instance of arrayOfElements
so far my linked list is
typedef struct LinkedListNode {
void** ElementArray;
struct LinkedListNode* next;
} LinkedListNode;
typedef struct {
LinkedListNode* head;
} LinkedList;
so the void** ElementArray will point to each arrayOfElements
void insert(LinkedList* head, Element inArrayOfElements)
{
LinkedListNode insertNode;
/* Points ElementArray to inArrayOfElements */
HOW DO I DO THIS AS ElementArray is a void**
/* Points next to the head */
(*insertNode).next = head;
/* Re-points head to new head of Linked List */
head = insertNode;
}
My Goal is to have something like this
LINKEDLIST
+---+ +---+---+----+
| | -> | | | | arrayofElements
+---+ +---+---+----+ +---+---+----+
| | -------------------> | | | |
+---+ +---+---+----+ +---+---+----+
| | -> | | | |
+---+ +---+---+----+ +---+---+----+
| | -------------------> | | | |
+---+ +---+---+----+
Question / TL;DR
My question is how do I make void** ElementArray (in the linked list) point to arrayOfElements.
If I understand your question correct, there is no need for double pointers. Just do:
typedef struct LinkedListNode {
Element* data;
struct LinkedListNode* next;
} LinkedListNode;
LinkedListNode* insert(LinkedListNode* head, Element* inArrayOfElements)
{
LinkedListNode* insertNode = malloc(sizeof(LinkedListNode));
insertNode->next = head;
insertNode->data = inArrayOfElements;
return insertNode;
}
Use it like:
head = insert(head, someArrayOfElements);
Note: The real code should check for NULL pointers but I omitted that for simplicity.
1st:
p = (int *)sp VS p = int *sp VS p = int (*sp)
2nd:
(struct node*) malloc(sizeof(struct node)) VS struct node* malloc(sizeof(struct node))
VS struct node (*malloc(sizeof(struct node)))
3rd:
#define cEEP_ABC *((CHAR *)ps8c_PROM( EEP_TEST+0x2B ))
What is the difference for the statement in 1st and 2nd question?
For 3rd question, *((CHAR *)ps8c_PROM( EEP_TEST+0x564 ))
^ ^
| |
| |
| |
---------------- What the purpose for these 2 pointer?
Can the statement change to this form: *(CHAR *ps8c_PROM( EEP_TEST+0x2B )) or *(CHAR (*ps8c_PROM( EEP_TEST+0x2B )))?
1st:
p = (int *)sp; //typecasting sp to int* and storing it in p
p = int *sp; //Declares sp as int* and its value is stored in p
p = int (*sp); //Compilation error
2nd:
(struct node*) malloc(sizeof(struct node)); //Allocates memory equal to size to struct node and returns a pointer to the start
Others: Compilation error.
3rd:
(CHAR *)ps8c_PROM( EEP_TEST+0x564 ) typecasts the return value of the function to char * and the leading * gives the value pointed by that address. So it returns a char.