简体   繁体   中英

C - Allocating memory to a pointer to a member in a Struct

I've already seen a lot of other questions, however I still can't seem to figure out how to initialize a pointer to a struct member that is also a pointer. Given my pointer to my struct (which contains a member that is a pointer) I want to initialize a pointer to that member pointer.

For example when adding a node to a linked list the parameter given in the examples which I have learned are addNode(**head, etc). I would like to know whether or not I need to allocate memory to this pointer and how to initialize it if I'm doing it wrong in the code below.

int row, col;
double val;
char nwln;

sp_tuples_node ** tuplepointer/* = malloc(sizeof(sp_tuples_node *));*/

FILE * inFile = fopen(input_file, "r");
sp_tuples * new_tuples = malloc(sizeof(sp_tuples));
tuplepointer = new_tuples->tuples_head;
fscanf(inFile, "%d %d%c", &row, &col, &nwln);

  //while not eof
  fscanf(inFile, "%d %d %d%c", &row, &col, &val, &nwln);
  addNode(tuplepointer, row, col, val);
  return new_tuples;

The line in question is separated by new lines the rest of the non completed code is there for context of calling the function and its functionality should be disregarded.

Thank you for any feedback regarding how to assign pointers to members that are pointers.

Whenever you declare a type pointer-to-pointer-to type you require two allocations before you can make use of any of the pointer-to type referenced through the pointer-to-pointer-to type (or at minimum one allocation of pointers and then an assignment of an existing object to each of the allocated pointers).

Take for example your declaration of:

sp_tuples_node **tuplepointer;

(presuming std_tuples_node is not some typedeffed pointer)

What you need to do is:

  • first allocate some number of pointers . Why? You have a pointer-to-pointer . That is a single-pointer holding the address of a pointer-to type . If you want reference 50 of the type object referred to, you must allocate 50 pointers so that tuplepointer points to a block of memory that contains 50 pointers to type sp_tuples_node .

For example:

tuplepointer = malloc (50 * sizeof *tuplepointer);    /* allocate 50 pointers */
if (!tuplepointer) {                                  /* validate allocation */
    perror ("malloc-tuplepointer");
    exit (EXIT_FAILURE);
}
  • second, you can allocate storage for each sp_tuples_node and assign the starting address for each block allocated to one of the 50 pointers in the block of memory you have allocated and assigned to tuplepointer above.

For example:

for (size_t i = 0; i < 50; i++) {
    tuplepointer[i] = malloc (sizeof *tuplepointer[i]);
    if (!tuplepointer[i]) {
        perror ("malloc-tuplepointer[i]");
        exit (EXIT_FAILURE);
    }
}

( note: if you always use the dereferenced pointer to set the typesize for the type you are allocating -- you will never get your typesize wrong)

Now you have allocated storage for 50 pointers and assigned the starting address to tuplepointer . You have also allocates storage for 50 - sp_tuples_node and you have assigned the starting address for each to one of the 50 pointers in the block assigned to tuplepointer . You can reference each sp_tuples_node using array-index notation as tuplepointer[i] .

If sp_tuples_node contains yet another pointer to some type as a member of the struct you can now allocate a block of storage and assign the starting address to that pointer. Say you have char *str; as a member of sp_tuples_node . You can then allocate:

size_t len = strlen(somestring);
tuplepointer[i]->str = malloc (len + 1);   /* allocate storage for str, assign to ptr */
/* validate allocation ... */
memcpy (typlepointer[i]->str, somestring, len + 1);

And so on and so forth... You can do this as many times as needed. The only thing you need to keep straight is whether you are allocating pointers, or allocating storage for an object. Obviously with a pointer-to-pointer-to type you are allocating pointers, when you derefernce once and need to allocate for pointer-to type you are allocating storage for an object.

How do you keep it straight?

Think of it this way. When you derefernce the type you are allocating for -- what do you have?

  • with a pointer-to-pointer-to type , when dereferenced you have pointer-to type (you are allocating pointers)
  • with a pointer-to type , when dereferenced you have type (you are allocating for an object)

Lastly, you mention linked-list in your question and you mention addNode(**head, etc) . That is different. You likely have in that case in the caller (say main() )

node *head;

and you are then calling:

addNode (&head, etc);

There the parameter type is pointer-to-pointer-to head because you are passing the address of the original pointer back in main() . head itself already has a valid address, so you do not allocate for head itself.

You pass &head so the function addNode receives the address of the original pointer instead of a copy-of the pointer. That way if you need to allocate storage for the node referenced through head you can allocate *head = malloc (sizeof **head); and upon function return head will point to the new block of memory allocated in addNode() without having to return and assign the starting address for the newly allocated block of memory.

Let me know if that helps clear it up. If not, I'm happy to try again.

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