简体   繁体   中英

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, eg:

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?

You have 2 errors in your code :

  1. int table* --> int *table - Declare pointer to integer

  2. *ht->size --> (*ht)->size - Imp to put brackets when you are not sure of operator precedence

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.

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 ?

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM