When do I exactly need a pointer with structs

Viewed 104

I really do not understand if and when do I need to declare a pointer to my data struct.

I have two programs and both works the same, but I cant figure out where should I need a pointer or not.

Here are the programs:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct data
{
    char *ptr;
};

void printStruct( struct data pers );

int main (void)
{
    struct data pers;   // Here pers is not a POINTER

    pers.ptr = malloc(sizeof (char) * 256);
    strcpy(pers.ptr, "Hello World");

    printStruct(pers);
    free(pers.ptr);
}

void printStruct( struct data pers ){
    printf("PTR = %s\n", pers.ptr);
}

When do I exactly need a pointer?

As you can see, here struct data pers; I declared a variable and in the next example I am using a pointer:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct data
{
    char *ptr;
};

void printStruct( struct data *pers );

void printStruct( struct data *pers ){
    printf("PTR = %s\n", pers->ptr);
}

int main (void)
{
    struct data *pers;   // Here pers is a POINTER
    pers = malloc(sizeof(*pers));
    pers->ptr = malloc(sizeof (char) * 256);
    strcpy(pers->ptr, "Hello World");

    printStruct(pers);

    free(pers->ptr);
    free(pers);
}
1 Answers

There are four cases where you have to use a pointer to a struct:

  1. You want a function to write to a parameter of struct type:
    struct foo { int member; }
    
    void updateFoo( struct foo *bar )
    {
      bar->member = some_new_value();
    }
    
    int main( void )
    {
      struct foo f = {0};
      ...
      updateFoo( &f );
    }
    
  2. You want to allocate one or more instances of a struct type dynamically:
    struct foo *farr = malloc( sizeof *farr * NUM_ELEMENTS );
    
  3. You're using a struct type with a flexible array member:
    struct foo { int x; char y[]; }
    
    struct foo *instance = malloc( sizeof *instance + LENGTH_FOR_Y_MEMBER );
    
  4. You want to define a self-referential type (i.e., each instance of struct foo points to a different instance of struct foo:
    struct list_node { int data; struct list_node *next; }
    
    This is a common implementation of a singly-linked list - each element of the list explicitly points to the next element in the list (or NULL if at the last element).

You may also choose to pass a pointer to a struct to a function, even if the function doesn't modify the parameter, just to save the overhead of creating a copy in the called function, especially if the struct type is large:

struct ginormous { /* define many large members here */ };

void blah( const struct ginormous *g )
{
  // do stuff with g
}
Related